How to convert SQL inner join to lambda linq query - linq

I am new in LINQ queries
and I need help to convert my sample SQL query to LINQ lambda query
select * from GRecommendations
inner join GSections
on GRecommendations.GSectionId = GSections.Id
where GSections.GaId = 646

There are two different methods you can use when GRecommendations is a collection.
var arrResult = //UNTESTED
GRecommendations
.Join(GSections.Where(sec => sec.GaId.Equals(646)),
rec => rec.GeSectionId,
sec => sec.Id,
(REC, SEC) => new { /*put here what you want selected*/ }
); //
or
var arrResult =
(
from rec in GRecommendations
join rec in GSections.Where(s => s.GaId.Equals(646)) on rec.GSectionId equals sec.GaId
select new {/*rec.something*/, /*sec.something*/}
);

Related

linq to entities Not in statement

I am new to linq to entities. I am trying to do a not in statement and when i run it i am getting noting back. But if i run the SQL equivalent i get data back.
The SQL statement that i am trying to replicate is
SELECT * FROM [SCRAPREASON] WHERE [CODE] NOT IN (SELECT [CODE] FROM [QUALITYALERTRULE]) ORDER BY [CODE]
The Linq i have at the moment is
var DefectCode = PumaOEEEntities.ScrapReasons
.Where(x => !PumaOEEEntities.QualityAlertRules.Any(y => y.Code != x.Code))
.Select(x => new { GroupID = x.Code}).ToList();
Can anyone see what i am doing wrong?
You should compare codes for equality (== instead of !=):
var reasons = PumaOEEEntities.ScrapReasons
.Where(x => !PumaOEEEntities.QualityAlertRules.Any(y => y.Code == x.Code))
.OrderBy(x => x.Code)
.ToList();
Generated SQL will look like:
SELECT
[Extent1].[Code] AS [Code],
// Other columns
FROM [dbo].[ScrapReasons] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[QualityAlertRules] AS [Extent2]
WHERE [Extent2].[Code] = [Extent1].[Code]
)
ORDER BY [Extent1].[Code] ASC
You can try Except like this
var DefectCode = PumaOEEEntities.ScrapReasons.Select(x=>x.Code)
.Except(PumaOEEEntities.QualityAlertRules.Select(y=>y.Code)).ToList();

Linq 2 SQL left Join with mono

I cant get the fallowing request working in Mono:
Without joins it would work.
when I only select t1 it also works, but I cant select something from both tables.
I think I want a left join, where I always have entries in t1 and IF the NameOfFile matches FileName then I want to have the tables joined.
Extra Question: When is my query executed? When I run the foreach loop?
var result = (
from t1 in db.Table1
join t2 in db.Table2 on t1.FileName equals t2.NameOfFile
into joinDep
from t3 in joinDep.DefaultIfEmpty ()
select new
{
Time = t1.WriteTime,
Name = t2.NameOfFile
}
)
.OrderByDescending (c => c.Time.Date)
.Take (10);
foreach (var entry in result)
{
Console.WriteLine (entry.Name );
}
Use this:
var query = from t1 in db.Table1
join t2 in db.Table2 on t1.FileName equals t2.NameOfFile into gj
from joinDep in gj.DefaultIfEmpty ()
select new
{
Time = t1.WriteTime,
Name = joinDep.NameOfFile
};
var result = query.OrderByDescending (c => c.Time.Date)
.Take (10);
Yes. Take uses deferred execution.

Linq query with two joins on inner select in EF

I'm trying to create a Linq query for EF that joins on 2 values from an inner select. Underneath you will find the SQL query that does the trick, things are much more tricky when trying to do so in Linq.
I use POCO object and would like the query to return the List and not an anonymous type. Is this possible with Linq to EF?
SELECT s1.*
FROM [Statistics] s1
INNER JOIN
(
SELECT MAX(CreateDate) as createdate
FROM [Statistics]
GROUP BY UserId
) s2
ON s1.UserId = s2.[UserId] and s1.CreateDate = s2.createdate
ORDER BY s1.Balance desc
You can do this with a Where or a Join.
from s1 in Statistics
join s2 in (from s in Statistics group s by s.UserId into g
select new { UserId = g.Key, CreateDate = g.Max (s => s.CreateDate) })
on new { s1.UserId, s1.CreateDate } equals new { s2.UserId, s2.CreateDate }
orderby s1.Balance descending
select s1;
Or,
from s1 in Statistics
from s2 in (from s in Statistics group s by s.UserId into g
select new { UserId = g.Key, CreateDate = g.Max (s => s.CreateDate) })
where s1.UserId == s2.UserId && s1.CreateDate == s2.CreateDate
orderby s1.Balance descending
select s1;

linq query, convert sql query to linq for VB.net

I am trying to get fields from one table and max(expirationDate) from another table. This is my original linq query:
tanks = (From t In db.Table1 _
Where t.CompanyID = txtCompanyID.Text.Trim() _
Join d In db.Table2 On t.TankID Equals d.TankID
Order By d.ExpireDate Descending
Select t).ToList
that brings back multiple expireDates, I only want the max(expireDate) for each record
The following sql query works, I just need to put it into a linq query
select t1.*,
(Select MAX(Table2.ExpireDate)
from Table2 as t2
where t2.TankID = t1.TankID)
as max_expire_date
from Table1 as t1
where t1.CompanyID = '5467'
order by t1.CargoTankID
Does anybody know how to get this into linq? Thanks
tanks = db.Table1.Where( t => t.CompanyId == txtCompanyID.Text.Trim() )
.Join( db.Table2, t1 => t1.TankID, t2 => t2.TankID, (t1,t2) => new { Company = t1, t2.ExpireDate } )
.GroupBy( t => t.Company, (c,e) => new { Company = c Expiration = e.Max( x => x.ExpireDate ) } )
.ToList();
Best guess at VB
Dim tanks = db.Table1.Where( Function(t) t.CompanyId == txtCompanyID.Text.Trim() ) _
.Join( db.Table2, Function(t1) t1.TankID, Function(t2) t2.TankID, Function(t1,t2) New Thing With { .Company = t1, .ExpireDate = t2.ExpireDate } ) _
.GroupBy( Function(t) t.Company, Function(c,e) New Thing With { .Company = c, .Expiration = e.Max( Function(x) x.ExpireDate ) } ) _
.ToList()

How do I use subquery, groupby, max, and top in single linqToSql statement?

Using LinqToSql, I need to return a single (L) for the most recent modDate in a join table (CL).
Tables:
L (Lid, meta1, meta2, ...)
CL (Cid, Lid, ModDate)
Here is sql that produces the expected result
SELECT l.*
FROM L l
INNER JOIN (
SELECT TOP 1 cl.Lid, MAX(cl.ModDate) as ModDate
FROM CL cl
INNER JOIN L l ON cl.Lid = l.Lid AND l.meta1 = 5
GROUP BY cl.Lid
ORDER BY MAX(cl.ModDate) DESC
) As m ON l.Lid = m.Lid
Simple enough. The subquery projects us to the ids. The query fetches those records with matching ids.
var subquery = db.L
.Where(L => L.meta1 = 5)
.SelectMany(L => L.CLs)
.GroupBy(CL => CL.Lid)
.OrderByDescending(g => g.Max(CL => CL.ModDate))
.Select(g => g.Key)
.Take(1)
var query = db.L
.Where(L => subquery.Any(id => L.Lid == id))
Reflecting on this further, you can get away from the subquery:
var query = db.L
.Where(L => L.meta1 = 5)
.SelectMany(L => L.CLs)
.GroupBy(CL => CL.Lid)
.OrderByDescending(g => g.Max(CL => CL.ModDate))
.Select(g => g.First().L);
As your provided query, I can interpret into this Linq.
var query = from l in Context.L
join m in (from cl in Context.CL
join l in Context.L on cl.Lid equals l.Lid
where l.meta1 == 5
group new { l.Lid, cl.ModDate } by cl.Lid into grp
select new { Lid = grp.Key, ModDate = grp.Max(g => g.ModDate) } into grp
order by grp.ModDate descending
select grp).Take(1) on l.Lid equals m.Lid
select l;
My SQL-fu isn't fabulous and it's before my first coffee, so I assume "l" in the outer query ends up being a completely different "l" to the one in the subquery?
I think this will do it, but you'll have to try to be sure :) It'll be well worth checking what the generated SQL looks like. If you didn't mind it executing as two queries, of course, it would be somewhat simpler.
// Can't do the "Take(1)" here or it will be executed separately
var subquery = from cl in context.CL
join l in context.L on cl.Lid = l.Lid
where l.meta1 = 5 // could put this in join clause
group cl.ModDate by cl.lid into grouped
order by grouped.Max() descending
select grouped.Key;
// But can take the first result of the join
// This may be simpler using dot notation instead of a query expression
var query = (from l in context.L
join lid in subquery
select l).Take(1);
(EDIT: I wasn't taking the max ModDate before. Doh. Also simplified grouping by using the ID as the key (which it was already) so we only need the ModDate as the group values.)

Resources