This question already has answers here:
LEFT OUTER JOIN in LINQ
(24 answers)
Closed 8 years ago.
I have a T-SQL query
SELECT *
FROM BPM.tblEvaluationCatalogPlan
JOIN BPM.tblEvaluationCatalog ON BPM.tblEvaluationCatalogPlan.EvaluationCatalogId =
BPM.tblEvaluationCatalog.EvaluationCatalogId
JOIN BPM.tblMeasureProcess ON BPM.tblEvaluationCatalog.MeasureProcessId =
BPM.tblMeasureProcess.MeasureProcessId
JOIN dbo.tblMeasureCatalog ON BPM.tblMeasureProcess.MeasureCatalogId =
dbo.tblMeasureCatalog.MeasureCatalogId
LEFT OUTER JOIN dbo.tblMeasureUnit ON dbo.tblMeasureCatalog.MeasureUnitId =
dbo.tblMeasureUnit.MeasureUnitId
And I've written a LINQ Query for it
from m in tblEvaluationCatalogPlan
join l in tblEvaluationCatalog.Where(y => y.PlanId == PlanId) on
m.EvaluationCatalogId equals l.EvaluationCatalogId
join k in tblMeasureProcess.Where(x => x.ProcessId == ProcessId) on
l.MeasureProcessId equals k.MeasureProcessId
join j in tblMeasureCatalog on k.MeasureCatalogId equals
j.MeasureCatalogId
join i in tblMeasureUnit on j.MeasureUnitId equals i.MeasureUnitId
select new EvaluationCatalogPlanEntity
{
EvaluationCatalogPlan = m,
EvaluationCatalog = l,
MeasureProcess = k,
MeasureCatalog = j,
MeasureUnit = i
}
But Their output aren't the same.
What is the exact equivalent of the T-SQL Query in LINQ?
Try http://msdn.microsoft.com/en-US/vstudio/ee908647.aspx#leftouterjoin
var leftFinal =
from l in lefts
join r in rights on l equals r.Left into lrs
from lr in lrs.DefaultIfEmpty()
select new { LeftId = l.Id, RightId = ((l.Key==r.Key) ? r.Id : 0 };
you should put code in the code format so it's easier to read.
I have been able to achieve this result with group joins. Take a look here:
http://msdn.microsoft.com/en-us/library/bb397895(v=vs.120).aspx
Should be possible to get what it seems you are looking for.
Related
This question already has answers here:
Linq-to-Entities Join vs GroupJoin
(3 answers)
Closed 7 years ago.
I am new to linq... and I am wondering if I am doing it right..
Here's my code...
var result = from a in ctx.ItemReceipts
join b in ctx.ItemReceiptStatusTypes on a.Status equals b.ItemReceiptStatusTypeID
join c in ctx.PurchaseOrders on a.ReferenceID equals c.PurchaseOrderID
into leftJoinItemReceipts
from d in leftJoinItemReceipts.DefaultIfEmpty()
where a.ItemReceiptID.Equals(ItemReceiptID)
select new
{
CItemReceiptID = a.ItemReceiptID,
CTransactionNumber = a.TransactionNumber,
CRemarks = a.Remarks,
CStatus = a.Status,
CStatusType = b.Description,
CReferenceID = a.ReferenceID,
CReferenceTypeID = a.ReferenceTypeID,
CTransactionDate = a.TransactionDate,
CDateReceived = a.DateReceived,
CTotalCost = a.TotalCost,
CPONumber = d.PONumber
};
It runs perfectly... but I really can't understand the into part.. I dunno if it's really a left join but gives me the data that I want... it gives me all data in itemreceipts even though they don't have something in common with PurchaseOrder....
I need explanation... better a comparison between mysql and linq...
from a in ctx.ItemReceipts
join b in ctx.ItemReceiptStatusTypes on a.Status equals b.ItemReceiptStatusTypeID
into leftJoinItemReceipts
from d in leftJoinItemReceipts.DefaultIfEmpty()
join c in ctx.PurchaseOrders on d.ReferenceID equals c.PurchaseOrderID
This will do a left join on ItemReceipts and ItemReceiptStatusTypes and then a inner join with PurchaseOrders
This question already has answers here:
LINQ Join with Multiple Conditions in On Clause
(3 answers)
Closed 8 years ago.
I have 2 Tables AtdDailyAttendance and AcdAdmissionSessionDetails. I want to join these 2 tables from linq based on 2 ids, which means in Sql this join looks like
SELECT a.Id, a.DateId,
a.StudentLedgerId, a.AttendanceTypeId,
a.SchoolId, a.UserId, a.SessionId,
d.ClassId,d.MediumId,
d.StreamId, d.ShiftId,
d.SectionId
FROM AtdDailyAttendance a INNER JOIN AcdAdmissionSessionDetail d
ON a.StudentLedgerId = d.StudentLedgerId AND a.SessionId = d.SessionId
But in LINQ I'm unable to do this. I tried this way
var query =
from a in dbCOntext.AtdDailyAttendances
join b in dbCOntext.AcdAdmissionSessionDetails
on a.StudentLedgerId equals b.StudentLedgerId
// on a.SessionId equlas b.SessionId
select new
{
a.AtdSetedDatesForAttendance,
a.DateId,
a.StudentLedgerId,
a.SchoolId,
a.UserId,
a.SessionId,
b.ClassId,
b.SectionId,
b.MediumId,
b.StreamId
}
var liResult = query.ToList();
Here I'm unable to perform join between SessionId.
I think you're looking for:
var liResult = (from a in dbCOntext.AtdDailyAttendances
join b in dbCOntext.AcdAdmissionSessionDetails
on new { a.StudentLedgerId, a.SessionId }
equals new { b.StudentLedgerId, b.SessionId}
See if this will work:
dbContext.AtdDailyAttendances.Join(dbContext.AcAdmissionSessionDetails, m => m.StudentLedgerId, n => n.StudentLedgerId, (m, n) => new{
m.AcdAdmissionSessionDetails,
m.DateId,
m.StudentLedgerId,
m.SchoolId,
m.UserId,
AttendanceSessionId = n.SessionId,
AdmissionSessionId = m.SessionId,
n.ClassId,
n.SectionId,
n.MediumId,
n.StreamId
}).Where(n => n.AttendanceSessionId == n.AdmissionSessionId).ToList();
This question already has answers here:
Linq-to-Entities Join vs GroupJoin
(3 answers)
Closed 1 year ago.
There are 0 to n departments in my company, 0 to n offices in 1 department, and 0 to n emplyees in 1 office.Now I need a query using linq to list emplyees's average age by department, if nobody in a department then default average is 0.
code is below:
DataContext ctx = new DataContext();
var q0 = from d in ctx.Departments
join o in ctx.Offices on d.Id equals o.DepartmentId
join e in ctx.Employees on o.Id equals e.OfficeId
group e by d into de
select new {
DepartmentId = de.Key.Id,
AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
};
var q1 = from d in ctx.Departments
join de in q0 on d.Id equals de.DepartmentId into des
from de in des.DefaultIfEmpty()
select new
{
DepartmentName = d.Name,
AverageAge = de == null ? 0 : de.AverageAge
};
var result = q1.ToList();
foreach (var item in result)
{
Console.WriteLine("{0}-{1}", item.DepartmentName, item.AverageAge);
}
ctx.Dispose();
But how to combine q0 and q1 to one query?
Were you meaning something along the lines of:
var newQ2 = from d in ctx.Departments
outer left join o in ctx.Offices on d.Id equals o.DepartmentId
outer left join e in ctx.Employees on o.Id equals e.OfficeId
group e by d into de
select new {
DepartmentId = de.Key.Id,
AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
};
Changed to:
var newQ2 = from d in ctx.Departments
join o in ctx.Offices on d.Id equals o.DepartmentId
join e in ctx.Employees on o.Id equals e.OfficeId
group e by d into de.DefaultIfEmpty()
select new {
DepartmentId = de.Key.Id,
DepartdentName = select d.Name from d where d.id = de.Key.Id,
AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
};
Addendum: I would use a sub-select to match up the extra name, not knowing your db layout I have improvised from your code, but you could make it more efficient and have a multipart join based on sub-selects as well. Sorry I cant test this code out at work, I can approximate fairly well, but would need some more info on where your department names are located if you need a more detailed answer:) I have changed the outer left joins back to joins, sorry I forgot in C# with linq you can use DefaultIfEmpty() to cause outer left join behaviour in code.
An outer left join will return nulls where there are no corresponding values, but will allow returns on any parts that do have a corresponding value. Join however will not return any null entries which I suspect is why you had the two queries?
The only caveat on the query I have presented is that you will need to infill any values you require before you use them if they are nulls, for example DepartmentId will need some logic to populate it in case DE is null.
Thank you all,I have got the answer:
var q1 =
from d in ctx.Departments
from o in ctx.Offices.Where(o => o.DepartmentId == d.Id).DefaultIfEmpty()
from e in ctx.Employees.Where(e => e.OfficeId == o.Id).DefaultIfEmpty()
group e by d into de
select new {
DepartmentName = de.Key.Name,
AverageAge = de.Average(e => e == null ? 0 : e.Age),
};
I am struggling with how to write the below equivalent as LINQ. Truly I guess I am only struggling with how I represent the INNER JOIN () portion. Is that called a Nested Join? Anonymous Join? I am not even sure. Anyway, big thanks to anyone who can point me true. Even if it is just what this is called so I can BING it properly.
SELECT p.PersonID, p.FirstName, p.MiddleName, p.LastName, cp.EnrollmentID, cp.EnrollmentDate, cp.DisenrollmentDate
FROM vwPersonInfo AS p
INNER JOIN (
SELECT c.ClientID, c.EnrollmentID, c.EnrollmentDate, c.DisenrollmentDate
FROM tblCMOEnrollment AS c
LEFT OUTER JOIN tblWorkerHistory AS wh
ON c.EnrollmentID = wh.EnrollmentID
INNER JOIN tblStaffExtended AS se
ON wh.Worker = se.StaffID
WHERE (wh.EndDate IS NULL OR wh.EndDate >= getdate())
AND wh.Worker = --WorkerID Param Here
) AS cp
ON p.PersonID = cp.ClientID
ORDER BY p.PersonID
just put the inner query in its own variable. (It will be translated into one single SQL expression)
var innerQuery = from x in db.tblCMOEnrollment
where ...
select ...;
var query = from a in vwPersonInfo
join b innerQuery on p.PersonID equals cp.ClientID
select ...;
I think you can do this by writing a second method and joining on that method:
private static IEnumerable<Table> GetData(int joinKey)
{
return (from x in context.TableB.Where(id => id.Key == joinKey select x).AsQueryable();
}
Then you can do your normal query:
var query = from c in context.TableA
join GetData(c.PrimaryKeyValue)
I have a beginners LINQ2SQL question. I have this huge (but not complex) SQL statement:
SELECT Artikel.ArtikelID,
Artikel.CategorieID,
Artikel.ImageFile,
Artikel.RetailPrijs,
ISNULL(ShopArtikel.VerkoopsPrijs, Artikel.VerkoopsPrijs) AS VerkoopsPrijs,
Artikel.ArtikelCode,
Artikel.InAssortimentSinds,
ArtikelTaal.ArtikelNaam,
ArtikelTaal.ArtikelOmschrijving
FROM Artikel
INNER JOIN ArtikelTaal ON Artikel.ArtikelID = ArtikelTaal.ArtikelID
INNER JOIN ShopArtikel ON Artikel.ArtikelID = ShopArtikel.ArtikelID
INNER JOIN Categorie ON Artikel.CategorieID = Categorie.CategorieID
INNER JOIN CategorieTaal ON Categorie.CategorieID = CategorieTaal.CategorieID
INNER JOIN Shop ON ShopArtikel.ShopId = Shop.ShopID
INNER JOIN CategorieGroepShop ON Shop.ShopID = CategorieGroepShop.ShopId
INNER JOIN Taal ON ArtikelTaal.TaalCode = Taal.TaalCode AND CategorieTaal.TaalCode = Taal.TaalCode
INNER JOIN CategorieGroepTaal ON Taal.TaalCode = CategorieGroepTaal.TaalCode AND CategorieGroepShop.CategorieGroepId = CategorieGroepTaal.CategorieGroepID
INNER JOIN CategorieGroep ON Categorie.CategorieGroepID = CategorieGroep.CategorieGroepID AND CategorieGroepTaal.CategorieGroepID = CategorieGroep.CategorieGroepID AND CategorieGroepShop.CategorieGroepId = CategorieGroep.CategorieGroepID
WHERE (Shop.ShopID = 23) AND
(Taal.TaalCode = 'dut') AND
(Artikel.Onzichtbaar = 0) AND
(Artikel.NietBestelbaar = 0) AND
(Categorie.Onzichtbaar = 0) AND
(Artikel.Voorraad >= Artikel.LevertijdDrempel)
and I am converting this to LINQ and have this:
var allProducts = from artikelen in dc.Artikels
join sa in dc.ShopArtikels on artikelen.ArtikelID equals sa.ArtikelID
join at in dc.ArtikelTaals on artikelen.ArtikelID equals at.ArtikelID
join cat in dc.Categories on artikelen.CategorieID equals cat.CategorieID
join catt in dc.CategorieTaals on cat.CategorieID equals catt.CategorieID
join catg in dc.CategorieGroeps on cat.CategorieGroepID equals catg.CategorieGroepID
join catgt in dc.CategorieGroepTaals on catg.CategorieGroepID equals catgt.CategorieGroepID
join sh in dc.Shops on sa.ShopId equals sh.ShopID
join catgs in dc.CategorieGroepShops on sh.ShopID equals catgs.ShopId
join tl in dc.Taals on new { tc1 = at.TaalCode, tc2 = catgt.TaalCode } equals new { tc1 = tl.TaalCode, tc2 = tl.TaalCode }
where sh.ShopID == shop.BLL.Business.ShopController.CurrentShop.Id
select dc.Artikels;
but I have the idea that I made some (minor) mistakes while joining.
any ideas please!
EDIT
I have rewritten the LINQ query to this:
var allProducts = from artikelen in dc.Artikels
join at in dc.ArtikelTaals on artikelen.ArtikelID equals at.ArtikelID
join sa in dc.ShopArtikels on artikelen.ArtikelID equals sa.ArtikelID
join cat in dc.Categories on artikelen.CategorieID equals cat.CategorieID
join catt in dc.CategorieTaals on cat.CategorieID equals catt.CategorieID
join sh in dc.Shops on sa.ShopId equals sh.ShopID
join catgs in dc.CategorieGroepShops on sh.ShopID equals catgs.ShopId
join tl in dc.Taals on new { tc1 = at.TaalCode, tc2 = catt.TaalCode } equals new { tc1 = tl.TaalCode, tc2 = tl.TaalCode }
join catgt in dc.CategorieGroepTaals on new { tl.TaalCode, catgs.CategorieGroepId } equals new { catgt.TaalCode, catgt.CategorieGroepID }
join catg in dc.CategorieGroeps on new { cat.CategorieGroepID, catgt.CategorieGroepID, catgs.CategorieGroepId } equals new { catg.CategorieGroepID, catg.CategorieGroepID, catg.CategorieGroepID }
where sh.ShopID == 230
select dc.Artikels;
but I have a syntax error after "dut" }
Edit 2:
changed the join and replaced "dut" with the corresponding field in the database.
still have the error after the first }
it says: type inference failed in the call to 'Join'
Some of the SQL joins have multiple join conditions, which you didn't put in the LINQ query.
If this is something that will be frequently run then you should rewrite it as a stored procedure. I believe it is too convoluted and complex for a LINQ statement - too hard to see what's going on.
There is a tool for it, but I didn't try it. May be it's usefull for you.
http://www.sqltolinq.com/
It looks like the error line is actually a "Where" cause but not "Joining".
You can actually split the whole long Linq statement into smaller Query.
so for this case, its better to split it like this:
var at = from a in dc.ArtikelTaals
where a.TaalCode == "dut"
select a;
var catt = from c in dc.CategorieTaals
where c.TaalCode == "dut"
select c;
.....
and you can join the IQueryable "at" and "catt" in your complex query later.