Linq query with Contains having null value - c#

var qry = from _Cr in _er.Courses
from _R in _er.ResultsHeaders
where _R.Studentid == studentid
&& !_Cr.CourseID.Contains( _R.CourseID )
select new Obj_getCourses
{
Courseid = _Cr.CourseID,
CourseName = _Cr.CourseName
};
_er.CoursesTable have 4 values in it and _er.ResultsHeader table is empty. I was expecting 4 values from query but the query is not returning any Value. This is the query I am trying to write in LINQ.
Select * \
from Courses \
where courseid not in (Select courseid from ResultsHeader where studentid = 123);
Help require.
Thanks in advance

This should give you your desired results. I have written it in C# statement style so hopefully that having it is LINQ style was not a pre-requisite...
var qry = _er.Courses
.Where( c => !c.CourseID.Contains(_er.ResultsHeader
.Where( r => r.StudentID == 123)
.Select(r => r.CourseID)
)
.Select(c => new Obj_getCourses
{
Courseid = c.CourseID,
Coursename = c.CourseName
});

To get SQL you posted, you should try following query:
var qry = from _Cr in _er.Courses
where !_er.ResultsHeader.Where(r => r.StudentId == studentId)
.Select(r => r.CourseID)
.Contains(_Cr.CourseID)
select new Obj_getCourses
{
Courseid = _Cr.CourseID,
CourseName = _Cr.CourseName
};

Related

Join where lambda query in EF Core 3.1

I have a problem to write in lambda query this sql query:
select c.Id, c.Name, c.SomeNumber, count(*) from TableA a
inner join TableB b
on a.Id = b.aId
inner join TableC c
on c.BId = b.Id
where b.Status = N'Approved'
and c.Scope = N'Scope1'
group by a.Id, a.Name, a.SomeNumber
Can you guys help me with this one ? I want to write lambda query to execute this in code. I'm using EF Core 3.1
This is what I ended up so far:
var query = await _dbContext.TableA.Where(a => a.TableB.Any(b => b.Status.Equals("Approved")
&& b.TableC.Any(c => c.Scope.Equals("Scope1"))))
.GroupBy(g => new { Id = g.Id, Name = g.Name, SomeNumber = g.SomeNumber })
.Select(s => new { Id = s.Key.Id, Name = s.Key.Name, SomeNumber = s.Key.SomeNumber, Count = s.Count() })
.GroupBy(g => g.Id).Select(s => new {Id = s.Key, Count = s.Count()}).ToListAsync();
Well, this is corrected query. I have used Query syntax which is more readable when query has lot of joins or SelectMany.
var query =
from a in _dbContext.TableA
from b in a.TableB
from c in b.TableC
where b.Status == "Approved" && c.Scope == "Scope1"
group a by new { a.Id, a.Name, a.SomeNumber } into g
select new
{
g.Key.Id,
g.Key.Name,
g.Key.SomeNumber,
Count = g.Count()
}
var result = await query.ToListAsync();
It's maybe easier to start from the many end and work up through the navigation properties
tableC
.Where(c => c.Scope == "Scope1" && c.BEntity.Status == "Approved")
.GroupBy(c => new
{
c.BEntity.AEntity.Id,
c.BEntity.AEntity.Name,
c.BEntity.AEntity.SomeNumber
})
.Select(g => new { g.Key.Id, g.Key.Name, g.Key.SomeNumber, Ct = g.Count()})
EF knows how to do joins when you navigate around the object tree in the where. By starting at the many and and working up to the 1 end of the relationship it means you don't have to get complex with asking "do any of the children of this parent have a status of ..."

Convert SQL query using 'count' clause, to LinQ

My SQL Server query (below) works perfectly fine, and I'm trying to convert it to LinQ in C#.
SQL Query:
SELECT addressline3, city, COUNT(*) as 'InstitutionNumber'
FROM institutionenquiries
WHERE CITY = 'AHMEDABAD'
GROUP BY addressline3, city
ORDER BY city;
Desired output is:
I'm able to draw the LinQ query in below format, which gives me correct output
(except for COUNT(*) as 'InstitutionNumber').
LINQ Query:
var obj = (from u in dbContext.InstitutionEnquiry
where u.City == data.Trim().ToLower()
select new {
AddressLine3 = u.AddressLine3.Trim().ToLower(),
City = u.City.Trim().ToLower(),
InstitutionNumber = (from a in dbContext.InstitutionEnquiry
where a.City == data.Trim().ToLower()
select a).Count()
}).ToList();
This gives me count for 'InstitutionNumber' = 3 for all.
I'm not able to get the count aspect correctly. I've referred to this post's answer and it gives me only count, but I'm not able to nest it within my LinQ query.
Any helpful inputs will be appreciated.
The first observation is that since SQL has a GROUP BY, LINQ should have a GroupBy, too.
The second observation is that since non-aggregate columns in SQL are group by columns, the results you select in LINQ would come from the group's key.
Now we can write the query:
var res = dbContext.InstitutionEnquiry
.Where(u => u.City == data.Trim().ToLower())
.GroupBy(u => new {
AddressLine3 = u.AddressLine3.Trim().ToLower(),
City = u.City.Trim().ToLower()
}).Select(g => new {
g.Key.AddressLine3,
g.Key.City,
Count = g.Count()
}).ToList();
I think you can use this LinQ :
var obj = dbContext.InstitutionEnquiry
// WHERE CITY = 'AHMEDABAD'
.Where(w => w.City == "AHMEDABAD") // => Note
// GROUP BY addressline3, city
.GroupBy(g => new {g.AddressLine3, g.City})
// SELECT addressline3, city, COUNT(*) as 'InstitutionNumber'
.Select(c => new {c.Key.AddressLine3, c.Key.City, InstitutionNumber = c.Count()})
// ORDER BY city
.OrderBy(o=> o.City)
.ToList();
Note: For ignoring case sensitivity You can use :
.Where(string.Equals(w.City.Trim(), data.Trim(), StringComparison.CurrentCultureIgnoreCase))
LINQ :
var obj = (from p in dbContext.InstitutionEnquiry
group p by new
{
p.addressline3,
p.city
} into grp
select new
{
grp.Key.addressline3,
grp.Key.city,
InstitutionNumber = grp.Count(),
}).ToList();
Equivalent Lambda expression :
var obj = dbContext.InstitutionEnquiry
.GroupBy(p => new { p.addressline3, p.city})
.Select(p => new { p.Key.addressline3, p.Key.city, InstitutionNumber = p.Count() })
.ToList();

Convert SUM / CASE WHEN / GROUP BY SQL query into LINQ

I am having a VERY hard time converting my simple SQL query to LINQ...
SELECT Id
,Location
,SUM( CASE
WHEN TransactionType = 'Out' THEN [Quantity] * -1
ELSE Quantity
END) AS StockQuantity
FROM Transactions
WHERE Id = 123
GROUP BY Id, Location
here is my best WRONG attempt...
var result = db.Transactions
.Where(r => r.Id == 123)
.GroupBy(r => r.Id, r => r.Location)
.Select(group => new
{
Id = r.Id,
Location = r.Location,
Quantity = sum(r.TransactionType == 2 ? r.Quantity * -1 : r.Quantity),
});
Thanks in advance
You are not using your grouped values. Your query should be like:
var result = db.Transactions
.Where(r => r.Id == 123)
.GroupBy(r => new { r.Id, r.Location} )
.Select(grp => new
{
Id = grp.Key.Id,
Location = grp.Key.Location,
Quantity = grp.Sum(t=> t.TransactionType == 2 ? t.Quantity * -1 : t.Quantity),
});
I would also use a different variable name than group in projection (Select) since it is a contextual keywords (with query expression)

Translate SQL to lambda LINQ with GroupBy and Average

I spend a few hours trying to translate simple SQL to lambda LINQ
SELECT ID, AVG(Score) FROM myTable
GROUP BY ID
Any idea?
from t in myTable
group t by new {
t.ID
} into g
select new {
Average = g.Average(p => p.Score),
g.Key.ID
}
or Lambda
myTable.GroupBy(t => new {ID = t.ID})
.Select (g => new {
Average = g.Average (p => p.Score),
ID = g.Key.ID
})
The equivalent in Linq-to-Objects would be something like the below.
var results = from row in myTable
group row by row.Id into rows
select new
{
Id = rows.Key,
AverageScore = rows.Average(row => row.Score)
};
It's only slightly different for an ORM like entity framework. Namely, you would need to go through the data context or an appropriate DbSet/ObjectSet.
var _result = from a in myTable
group a by a.ID into g
select new
{
ID = g.Key.ID,
AverageResult = g.Average(x => x.Score)
}

How do I perform a SelectMany in C# query syntax using a many-to-many joining table?

I have the following c# statement that via EF generates exactly what I'm looking for but am curious as to how I'd write this with query syntax:
var dealers = this.Dealers
.SelectMany (d => d.Brands, (d, col) => new { Name = d.Name, Brand = col.Name, StatusId = d.StatusId })
.Where (d => d.StatusId == 1);
var dealers = from d in Dealers
from col in d.Brands
where d.StatusId == 1
select new { Name = d.Name,
Brand = col.Name,
StatusId = d.StatusId };

Categories