linq to entities left outer join - linq

select SF.FOLDER_NAME,SF.CREATED_DATE,COUNT(st.FOLDER_ID)
from SURVEY_FOLDER SF with (nolock) left outer join SURVEY_TEMPLATE ST with (nolock)
on SF.FOLDER_ID=ST.FOLDER_ID
group by SF.FOLDER_NAME,SF.CREATED_DATE
I need this query in Linq :
I have tried this query,but unable to group by.
My Linq Query :
var data = (from xx in VDC.SURVEY_FOLDER
join yy in VDC.SURVEY_TEMPLATE
on xx.FOLDER_ID equals yy.FOLDER_ID into g
from grt in g.DefaultIfEmpty()
select
new
{
xx.FOLDER_NAME,
xx.CREATED_DATE,
count = g.Count()
}).ToList();

I got the Answer :
var data5 = (from SF in VDC.SURVEY_FOLDER
join ST in VDC.SURVEY_TEMPLATE on new { FOLDER_ID = SF.FOLDER_ID } equals new { FOLDER_ID = (Int64)ST.FOLDER_ID } into ST_join
from ST in ST_join.DefaultIfEmpty()
group new { SF, ST } by new
{
SF.FOLDER_NAME,
SF.CREATED_DATE
} into g
select new
{
g.Key.FOLDER_NAME,
CREATED_DATE = (DateTime?)g.Key.CREATED_DATE,
Column1 = (Int64?)g.Count(p => p.ST.FOLDER_ID != null)
}).ToList();

Related

LINQ left outer join NullReferenceException

I am getting NullReferenceException when doing left outer join.
Similar query works in LINQ Pad but not in Visual Studio 2015. System.NullReferenceException was unhandled by user code
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Thanks in advance.
.Net Core LINQ Code that does not work:
public IEnumerable<R> GetAll()
{
var results =
from a in uow.R.GetAll()
join b in uow.SSR.GetAll() on a.ID equals b.RID into g9
from c in g9.DefaultIfEmpty()
join d in uow.SS.GetAll() on c.SSID equals d.ID into g10
from e in g10.DefaultIfEmpty()
select new
{
a.Id,
SSID = c == null ? null : (int?)c.SSID,
e.Name
};
List<R> rList = new List<R>();
foreach (var a in results)
{
resourceList.Add(new R { ID = a.Id, SSID = a.SSID });
}
return rList.ToArray<R>();
}
`
var Result =
from a in Tbl_R
join b in Tbl_SS on a.ID equals b.RID into g9
from c in g9.DefaultIfEmpty()
join d in Lu_SS on c.SSID equals d.SSID into g10
from e in g10.DefaultIfEmpty()
select new
{
a.ID,
SSID = c == null ? null : (int?)c.SSID,
e.Name
};
Result.Dump();
SELECT t2.ID,
ISNULL(t17.SSID,'') as SSID
ISNULL(t17.Name,'') as Name
FROM R t2
LEFT JOIN SSR t16 ON t16.RID=t2.ID
LEFT JOIN SS t17 ON t16.SSID=t17.SSID

LINQ Multiple table left join, distinct count not giving proper result

I am sql query us producing correct result, but when i'm doing the same in LINQ. Output is incorrect. Please let me know where my making mistake.
Following linq query that i created.
LINQ Query:
List<UserModel> Model = (from users in db.UserM
join ct in db.CustT on users.UserId equals ct.UserID into group1
from g1 in group1.DefaultIfEmpty()
join ti in db.TestIn on g1.TestId equals ti.TestID into group2
from g2 in group2.DefaultIfEmpty()
where (users.CustomerId==CustomerId) && (users.RoleId == 4) && (users.Status == 1)
group new
{
g2.TestInvitationID,
g2.TestID,
}
by new
{
users.FirstName,
users.CreatedOn,
users.Email,
users.UserId
} into group4
select new UserModel
{
Name = group4.Key.FirstName,
CreatedOn = group4.Key.CreatedOn,
EmailId = group4.Key.Email,
UserId = group4.Key.UserId,
NoOfTestTaken = group4.Select(x=>x.TestID).Distinct().Count(),
NoOfInvitationsSent = group4.Count(x => x.TestInvitationID != 0)
}).ToList();
SQL Query:
SELECT IsNull(COUNT(distinct TS.TestId),0) AS NoOfTests,
IsNull(COUNT(TS.TestInvitationID),0) AS NoOfInvitations,
UM.Email,
UM.UserId,
UM.FirstName,
UM.CreatedOn
FROM UserM as UM
left JOIN CustT AS CT
ON UM.UserId=CT.UserId
left JOIN TestIn AS TS
ON TS.TestId = CT.TestId
WHERE UM.CustomerId=41
AND UM.RoleId=4
and UM.[Status]=1
GROUP BY UM.UserId, UM.Email, UM.FirstName, UM.CreatedOn
Tables:
"UserM" - columns: UserId, Email, FirstName, CreatedOn
"CustT" - columns: TestId, UserId,
"TestIn" - columns: TestInvitationId, TestId
The difference between SQL COUNT(expr) and LINQ Count is that the former excludes NULL values, which produces a difference when used on right side of a left outer join with no matching records (SQL will produce 0 while LINQ 1). The closest LINQ equivalent is Count(expr != null).
So the direct translation of your SQL query would be like this (note that the generated SQL query could and most likely will be different):
(A side note: When converting SQL query to LINQ, it's good to use the same aliases to make it easier to see the mappings)
var query =
from um in db.UserMasters
join ct in db.CustTests on um.UserId equals ct.UserID
into ctGroup from ct in ctGroup.DefaultIfEmpty() // left outer join
join ts in db.TestInvitaions on ct.TestId equals ts.TestID
into tsGroup from ts in tsGroup.DefaultIfEmpty() // left outer join
where um.CustomerId == UserSession.CustomerId
&& um.RoleId == 4
&& um.Status == 1
group ts by new { um.UserId, um.Email, um.FirstName, um.CreatedOn } into g
select new UserModel
{
Name = g.Key.FirstName,
CreatedOn = g.Key.CreatedOn,
EmailId = g.Key.Email,
UserId = g.Key.UserId,
NoOfTestTaken = g.Where(ts => ts != null).Select(ts => ts.TestID).Distinct().Count(),
NoOfInvitationsSent = g.Count(ts => ts != null)
};
var result = query.ToList();
I suspect that the following row is the problem because is not the same like in your sql:
Linq:
NoOfInvitationsSent = group4.Count(x => x.TestInvitationID != 0)
SQL:
IsNull(COUNT(TS.TestInvitationID),0) AS NoOfInvitations
Due to counting items from a left join Linq should be instead:
NoOfInvitationsSent = group4.Where(i => i != null).Count()
To put it all together, with a bit of better formatting:
var model = (from users in db.UserMasters
join ct in db.CustTests on users.UserId equals ct.UserID into group1
from ct in group1.DefaultIfEmpty()
join ti in db.TestInvitaions on ct.TestId equals ti.TestID into group2
from ct in group2.DefaultIfEmpty()
where users.CustomerId == UserSession.CustomerId &&
users.RoleId == 4 &&
users.Status == 1
group new { ct.TestInvitationID, ct.TestID }
by new
{
users.FirstName,
users.CreatedOn,
users.Email,
users.UserId
} into grouping
select new UserModel
{
Name = grouping.Key.FirstName,
CreatedOn = grouping.Key.CreatedOn,
EmailId = grouping.Key.Email,
UserId = grouping.Key.UserId,
NoOfTestTaken = grouping.Where(i => i != null).Select(x => x.TestID).Distinct().Count(),
NoOfInvitationsSent = grouping.Where(i => i != null).Count()
}).ToList();

Linq Left Join not working

I am trying to get this query into Linq
SELECT [ID], [Name], LastSync, Phase
FROM [Store]
LEFT JOIN (
SELECT GLog.[StoreId] AS [StoreId], LastSync, Phase
FROM [GGCSyncLog] AS GLog
INNER JOIN (
SELECT MAX(G1.[DateTime]) AS LastSync, G1.[StoreId]
FROM [GGCSyncLog] AS G1
GROUP BY G1.[StoreId]
) AS G2 ON (GLog.[StoreId] = G2.[StoreId]) AND (GLog.[DateTime] = G2.[LastSync])
) AS MostRecentLog ON Store.[ID] = MostRecentLog.[StoreId]
Its results are
ID Name LastSync Phase
1 Sarasota 2010-07-31 5
2 Wellington 2010-07-31 8
3 Tampa International 2013-03-12 8
5 Events NULL NULL
6 PO Holding Store NULL NULL
My Linq returns the correct results except I'm missing the two rows with the null LastSync & Phase. Any idea what's wrong?
from s in Stores
join gLog in
(from g1 in GGCSyncLogs.DefaultIfEmpty()
join g in
(from g in GGCSyncLogs
group g by g.StoreId into gM
select new {
StoreId = gM.Key, LastSync = gM.Max(gg=>gg.DateTime) })
on new {g1.StoreId, LastSync = g1.DateTime} equals new {g.StoreId, g.LastSync}
select new {g1.StoreId, g.LastSync, g1.Phase})
on s.ID equals gLog.StoreId
select new {s.ID, s.Name,
LastSync = (gLog != null ? (DateTime?)gLog.LastSync : null),
Phase = (gLog != null ? (int?)gLog.Phase : null) }
You should read about join clause and How to: Perform Left Outer Joins.
It's hard to get working solution without database here, but hope this will help you get back on track:
var g2 = from g1 in GGCSyncLogs
group g1 by g1.StoreId into gM;
var MostRecentLogs = from gLog in GGCSyncLogs
join g in g2 on new { gLog.StoreId, LastSync = gLog.DateTime} equals new { g.StoreId, g.LastSync }
select new { gLog.StoreId, LastSync = gLog.Date, Phase = gLog.Phase };
var results = from s in Stores
join gLog in MostRecentLogs on s.Id equals gLog.StoreId into gl
from l in gl.DefaultIfEmpty(new { LastSync = null, Phase = null })
select new {
s.Id,
s.Name,
l.LastSync,
l.Phase
};
I had to use an "into"
from s in Stores
join gRec in
(from g in GGCSyncLogs
join g2 in
(from g1 in GGCSyncLogs
group g1 by g1.StoreId into gM
select new {StoreId = gM.Key,LastSync = gM.Max(gg=>gg.DateTime)})
on new {g.StoreId, LastSync = g.DateTime} equals new {g2.StoreId, g2.LastSync}
select new {g.StoreId, g2.LastSync, g.Phase})
on s.ID equals gRec.StoreId into gRec2
from gRec3 in gRec2.DefaultIfEmpty()
select new {s.ID, s.Name,
LastSync = (gRec3 != null ? (DateTime?)gRec3.LastSync : null),
Phase = (gRec3 != null ? (int?)gRec3.Phase : null) }

Multiple conditions with Joins in Linq

For the below code it gives the error
type reference failed in the call to Join
how can to fix this
var unp = from v in context.student.Include("subjects").Include("marks")
join n in context.AllStudents
on v.StudentDetails.student_Id equals n.Id
join ss in context.StudentHistory
on v.StBacklogs_Id equals ss.Id
join userName in context.Users
on v.CreatedBy_Id equals userName.Id
join externalId in context.Books
on new { ss.BookNumber, ss.Id } equals new { externalId.BookNumber, externalId.Id }
select new { v, n, ss, userName,externalId };

linq nested query

I have a query that has the following
var myvar = from table in MyDataModel
where.....
select new MyModel
{
modelvar1 = ...,
modelvar2 = (from..... into anothervar)
}
What I want to do is have modelvar2 be a join between the result I currently get from anothervar with another table in MyDataModel.
Thanks
The parenthesis looks more like a subquery than a join. This is how you do a join.
Example tables from the AdventureWorks database.
using (DataClasses1DataContext context = new DataClasses1DataContext())
{
// If you have foreign keys correctly in your database you can
// join implicitly with the "dot" notation.
var myvar = from prod in context.Products
where prod.ListPrice < 10
select new
{
Name = prod.Name,
Category = prod.ProductSubcategory.ProductCategory.Name,
};
// If you don't have foreign keys you need to express the join
// explicitly like this
var myvar2 = from prod in context.Products
join prodSubCategory in context.ProductSubcategories
on prod.ProductSubcategoryID equals prodSubCategory.ProductSubcategoryID
join prodCategory in context.ProductCategories
on prodSubCategory.ProductCategoryID equals prodCategory.ProductCategoryID
where prod.ListPrice < 10
select new
{
Name = prod.Name,
Category = prodCategory.Name,
};
// If you REALLY want to do a subquery, this is how to do that
var myvar3 = from prod in context.Products
where prod.ListPrice < 10
select new
{
Name = prod.Name,
Category = (from prodSubCategory in context.ProductSubcategories
join prodCategory in context.ProductCategories
on prodSubCategory.ProductCategoryID equals prodCategory.ProductCategoryID
select prodCategory.Name).First(),
};
// If you want to get a list from the subquery you can do like this
var myvar4 = from prodCategory in context.ProductCategories
select new
{
Name = prodCategory.Name,
Subcategoreis = (from prodSubCategory in context.ProductSubcategories
where prodSubCategory.ProductCategoryID == prodCategory.ProductCategoryID
select new { prodSubCategory.ProductSubcategoryID, prodSubCategory.Name }).ToList(),
};
}
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[ShipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPostalCode], [t0].[ShipCountry]
FROM [Orders] AS [t0]
INNER JOIN ([Order Details] AS [t1]
INNER JOIN [Products] AS [t2] ON [t1].[ProductID] = [t2].[ProductID]) ON [t0].[OrderID] = [t1].[OrderID]
can be write as
from o in Orders
join od in (
from od in OrderDetails join p in Products on od.ProductID equals p.ProductID select od)
on o.OrderID equals od.OrderID
select o

Resources