How to use left outer join in LINQ for SQL query? - c#

How can I use left outer join in LINQ for the following SQL query?
SELECT a.EventID, a.PrizeId, b.PrizeName, b.PrizeValue, c.FightID, c.Winnerid, c.WinnerName
FROM tblUserprize a
JOIN tblPrizeDetails b
ON a.PrizeId=b.PrizeId
LEFT OUTER JOIN tblWinnersList c
ON a.EventID=c.EventID AND a.PrizeId=c.PrizeId AND c.FightID = 1534
WHERE a.EventID = 1320

It should look like this:
var userPrize = (
from a in tblUserprize
join b in tblPrizeDetails on a.PrizeId equals b.PrizeId
join c in tblWinnersList on new { a.EventID, a.PrizeId } equals new { c.EventID, c.PrizeId } into joinedTables
from item in joinedTables.DefaultIfEmpty()
where a.EventID == 1320 && item.FightID == 1534
select new
{
a.EventID,
a.PrizeId,
b.PrizeName,
b.PrizeValue,
item.FightID,
item.Winnerid,
item.WinnerName
});

Related

Join Table Group By Summary On Linq

Hi I try to convert the SQL query to LINQ.
SELECT C.ID, SUM(S.AMOUNT*CS.PRICE) AS TOTALCATEGORYSUMMARY
FROM CATEGORY C
INNER JOIN PRODUCT P ON P.CATEGORYID=C.ID
INNER JOIN PSTOCK S ON S.PRODUCTID=P.ID
INNER JOIN PCOST CS ON CS.PRODUCTID=P.ID
GROUP BY C.ID
I try as below:
var qry = from c in categories
join p in products on c.Id equals p.CategoryId
join s in stoks on p.Id equals s.ProductId
join t in costs on p.Id equals t.ProductId
group new {c} by new { c.Name,s.Stock,t.Amount } into ct
select (new { ct.Key.Name, AllCost=ct.Key.Amount * ct.Key.Stock });
How can I do this?
From your SQL query, your LINQ statement should be:
var qry = from c in categories
join p in products on c.Id equals p.CategoryId
join s in stoks on p.Id equals s.ProductId
join t in costs on p.Id equals t.ProductId
group new { c.Id, s.Amount, t.Price } by c.Id into ct
select new { Id = ct.Key.Id, AllCost = ct.Sum(x => x.Amount * x.Price) };
References
Group by single property
Enumerable.Sum method

Selecting max in linq query or rewriting to method chain syntax

I managed to turn this SQL query:
SELECT c.carId, c.Codename, count(c.CarId) as [CarCount],
FROM [DbEfTesting].[dbo].[Cars] c
left join Accessories a on c.CarId = a.CarId
left join CarsPeople cp on cp.CarId = c.CarId
left join People p on cp.PersonId = p.PersonId
group by c.CarId, c.Codename
into a LINQ query:
var x = from c in _context.Cars
join a in _context.Accessories on c.CarId equals a.Car.CarId
join j in _context.CarsPeople on c.CarId equals j.CarId
join p in _context.People on j.PersonId equals p.PersonId
group c by new { c.CarId, c.Codename } into g
select new VMCarAggregate()
{
CarId = g.Key.CarId,
Codename = g.Key.Codename,
CarCount = g.Count()
};
But now I'm lost trying to include a max value e.g the SQL:
SELECT c.carId, c.Codename, count(c.CarId) as [CarCount], max(a.AccessoryId) ...
I googled it and found lots of answers for method syntax. If I were using method chain syntax, I know I could do something like this:
_context.Accessories.Max(a => a.AccessoryId);
but I can't figure out how to do the group by in method chain syntax so either:
How can I convert that query to method syntax?
or
How can I inject a select on the max a.AccessoryId in the LINQ query format?
Try the below code once:
var x = from c in _context.Cars
join a in _context.Accessories equals a.Car.CarId
join j in _context.CarsPeople on c.CarId equals j.CarId
join p in _context.People on j.PersonId equals p.PersonId
group new { c.CarId, c.Codename, a.AccesoryId } by new { c.CarId, c.Codename } into g
select new
{
CarId = g.Key.CarId,
Codename = g.Key.Codename,
CarCount = g.Count(),
MaxAccesory = g.Max(z => z.AccesoryId)
};

Linq join returning parent even when child is null

I want to select all rows where fake2 is null AND all rows with a join on fake2
The code below does it fine, but I want to do it all in a select linq query to increase efficiency.
var rows = (
from a in crmLinqContext.fakeSet
join b in crmLinqContext.fake2Set on a.fake2.Id equals b.Id
join c in crmLinqContext.fake3Set on b.field equals c.field
where c.anotherField == "THIS_BIT_OF_TEXT"
select a);
List<myObject> objects = new List<myObject>();
foreach(var row in rows)
{
objects.Add(row);
}
rows = (
from a in crmLinqContext.fakeSet
where s.fake2 == null
select a);
foreach (var row in rows)
{
objects.Add(row);
}
return objects;
Use left join in linq something like below, it is not tested but what it does is that it left outer joins fakeSet and fakeSet2.
var rows =
from a in crmLinqContext.fakeSet
join b in crmLinqContext.fake2Set on a.fake2.Id equals b.Id into subset
from b in subset.DefaultIfEmpty()
join c in crmLinqContext.fake3Set on b.field equals c.field
where c.anotherField == "THIS_BIT_OF_TEXT"
select a;
var rows = (
from a in crmLinqContext.fakeSet
join b in crmLinqContext.fake2Set on a.Id equals b.Id
join c in crmLinqContext.fake3Set on b.field equals c.field
where c.anotherField == "THIS_BIT_OF_TEXT"
select a)
.Concat(
from a1 in crmLinqContext.fakeSet
where a1.fake2 == null
select a1);

SQL to Linq multiple tables left outer join

I have this query in SQL, and I want it to implement it in LINQ using Entity Framework, but how can I apply multiple tables left outer joins?
SELECT p.BookMastId as mastId
FROM BookMast p
left outer JOIN (SELECT y.BookMastId as Id, t.VrsnMastId as vrsn FROM BookReceiptMast t
left outer JOIN BookReceiptDtl y
on t.BookReceiptMastId = y.BookReceiptMastId) s
on p.BookMastId = s.Id where s.vrsn = 2
you can just use from var in collection join in syntax, something like this:
using(var cxt = new YourDataBaseContext()){
var firstJoin = from t in cxt.BookReceiptMast
join y in cxt.BookReceiptDtl
on t.BookReceiptMastId equals y.BookReceiptMastId
into yTemp
from y in yTemp.DefaultIfEmpty()
select new
{
Id = y != null ? y.BookMastId : 0,
vrsn = t.VrsnMastId
};
var allTables = from p in cxt.BookMast
join s in firstJoin
on p.BookMastId equals s.Id
into sTemp
from s in sTemp
where s.vrsn == 2
select new
{
mastId = p.BookMastId
};
}
I hope it helps you.

LINQ query with sub-query on LEFT JOIN conditions

I have these queries in SQL and LINQ that were built to retrieve the same data. Unfortunately they are retrieving different amount of records (LINQ returns 1555 values, and SQL returns 1969) and I can't figure out why.
Please help me to find out what I'm missing. Follows the queries:
SQL:
SELECT l.Lease_Detail_ID, l.Lease_ID, l.XRef_Lease_ID, v.Vendor_Name, l.Description, c.County, l.Amount, l.Payment_Due_Date,
l.Lease_Type, l.Location_ID, l.Active, l.Expiration_Date, a.Authorized, p.Payment_Date
FROM tblfLeaseDetail AS l
LEFT JOIN tblvVendor AS v ON l.Vendor_ID = v.Vendor_ID
LEFT JOIN tblvCounty AS c ON l.County_ID = c.County_ID
LEFT JOIN tblfAuthorization AS a ON l.Lease_Detail_ID = a.Lease_Detail_ID
AND a.Authorization_ID = (SELECT TOP 1 Authorization_ID
FROM tblfAuthorization
WHERE Lease_Detail_ID = l.Lease_Detail_ID
ORDER BY Authorized_Date)
LEFT JOIN tblfPayment AS p ON l.Lease_Detail_ID = p.Lease_Detail_ID
AND p.Payment_ID = (SELECT TOP 1 Payment_ID
FROM tblfPayment
WHERE Lease_Detail_ID = l.Lease_Detail_ID
ORDER BY payment_date)
ORDER BY l.Lease_Detail_ID
LINQ: (Edited after a few comments)
var leaseList = (from l in leases.tblfLeaseDetails
join v in leases.tblvVendors on l.Vendor_ID equals v.Vendor_ID into lv
from jlv in lv.DefaultIfEmpty()
join c in leases.tblvCounties on l.County_ID equals c.County_ID into lc
from jlc in lc.DefaultIfEmpty()
join a in leases.tblfAuthorizations on l.Lease_Detail_ID equals a.Lease_Detail_ID into la
from jla in la.DefaultIfEmpty()
where jla.Authorization_ID == (from aj in leases.tblfAuthorizations
where aj.Lease_Detail_ID == l.Lease_Detail_ID
orderby aj.Authorized_Date ascending
select aj.Authorization_ID).FirstOrDefault()
join p in leases.tblfPayments on l.Lease_Detail_ID equals p.Lease_Detail_ID into lp
from jlp in lp.DefaultIfEmpty()
where jlp.Payment_ID == (from pj in leases.tblfPayments
where pj.Lease_Detail_ID == l.Lease_Detail_ID
orderby pj.Payment_Date ascending
select pj.Payment_ID).FirstOrDefault()
select new LeaseViewModel()
{
Lease_Detail_ID = l.Lease_Detail_ID,
Lease_ID = l.Lease_ID,
XRef_Lease_ID = l.XRef_Lease_ID,
Vendor_Name = jlv.Vendor_Name,
Description = l.Description,
County = jlc.County,
Amount = l.Amount,
Payment_Due_Date = l.Payment_Due_Date,
Lease_Type = l.Lease_Type.ToString(),
Location_ID = l.Location_ID,
Active = l.Active,
Expiration_Date = l.Expiration_Date,
Authorized = jla.Authorized,
Payment_Date = jlp.Payment_Date
});
EDIT:
After analyzing the run-time SQL query generated by LINQ statement I found out that it's creating the Authorized sub-query in the wrong place. Here is what it looks like:
SELECT [t0].[Lease_Detail_ID], [t0].[Lease_ID], [t0].[XRef_Lease_ID], [t1].[Vendor_Name] AS [Vendor_Name], [t0].[Description], [t2].[County] AS [County], [t0].[Amount], [t0].[Payment_Due_Date], [t0].[Expiration_Date], [t3].[Authorized] AS [Authorized], CONVERT(NVarChar(1),[t0].[Lease_Type]) AS [Lease_Type], [t0].[Location_ID], CONVERT(Int,[t0].[Active]) AS [Active], [t4].[Payment_Date] AS [Payment_Date]
FROM [dbo].[tblfLeaseDetail] AS [t0]
LEFT OUTER JOIN [dbo].[tblvVendor] AS [t1] ON [t0].[Vendor_ID] = ([t1].[Vendor_ID])
LEFT OUTER JOIN [dbo].[tblvCounty] AS [t2] ON [t0].[County_ID] = ([t2].[County_ID])
LEFT OUTER JOIN [dbo].[tblfAuthorization] AS [t3] ON ([t0].[Lease_Detail_ID]) = [t3].[Lease_Detail_ID]
LEFT OUTER JOIN [dbo].[tblfPayment] AS [t4] ON ([t0].[Lease_Detail_ID]) = [t4].[Lease_Detail_ID]
WHERE ([t4].[Payment_ID] = ((SELECT TOP (1) [t5].[Payment_ID] FROM [dbo].[tblfPayment] AS [t5] WHERE [t5].[Lease_Detail_ID] = ([t0].[Lease_Detail_ID])
ORDER BY [t5].[Payment_Date] )))
AND ([t3].[Authorization_ID] = (( SELECT TOP (1) [t6].[Authorization_ID]
FROM [dbo].[tblfAuthorization] AS [t6]
WHERE [t6].[Lease_Detail_ID] = ([t0].[Lease_Detail_ID])
ORDER BY [t6].[Authorized_Date] )))
The problem is that it only made more confuse, once Payment and Authorized joins have exactly the same structure.
after some research I finally found how to do it. Here is the LINQ query that generates the SQL I was trying to get:
var leaseList = (from l in leases.tblfLeaseDetails
join p in leases.tblfPayments
on l.Lease_Detail_ID equals p.Lease_Detail_ID into lp
from jlp in lp.Where(x => x.Payment_ID == (from pj in leases.tblfPayments
where pj.Lease_Detail_ID == l.Lease_Detail_ID
orderby pj.Payment_Date ascending
select pj.Payment_ID).FirstOrDefault()).DefaultIfEmpty()
join a in leases.tblfAuthorizations on l.Lease_Detail_ID equals a.Lease_Detail_ID into la
from jla in la.Where(x => x.Authorization_ID == (from aj in leases.tblfAuthorizations
where aj.Lease_Detail_ID == l.Lease_Detail_ID
orderby aj.Authorized_Date ascending
select aj.Authorization_ID).FirstOrDefault()).DefaultIfEmpty()
join v in leases.tblvVendors on l.Vendor_ID equals v.Vendor_ID into lv
from jlv in lv.DefaultIfEmpty()
join c in leases.tblvCounties on l.County_ID equals c.County_ID into lc
from jlc in lc.DefaultIfEmpty()
select new LeaseViewModel()
{
Lease_Detail_ID = l.Lease_Detail_ID,
Lease_ID = l.Lease_ID,
XRef_Lease_ID = l.XRef_Lease_ID,
Vendor_Name = jlv.Vendor_Name,
Description = l.Description,
County = jlc.County,
Amount = l.Amount,
Payment_Due_Date = l.Payment_Due_Date,
Lease_Type = l.Lease_Type.ToString(),
Location_ID = l.Location_ID,
Active = l.Active,
Expiration_Date = l.Expiration_Date,
Authorized = jla.Authorized,
Payment_Date = jlp.Payment_Date
});

Categories

Resources