LINQ to SQL: Two left outer join with multiple join conditions - linq

Here's my SQL query:
Select <a bunch of columns>
from fields f
join Table1 c1 on c1.fieldID = f.ID and c1.year = 2014
join Table2 fRes on f.ID = fRes.fieldID
join Table3 stst on f.ID = stst.fieldID
join Table4 model on c1.ID = model.yearID
left join Table5 fA on f.ID = fA.fieldID and fA.year = 2014
left join Table6 nA on f.ID = nA.fieldID and nA.year = 2014
where fA.sourcename IS NULL and nA.Sourcename IS NULL
LINQ to SQL:
from f in BasicDataAccess.Data.FieldsList
join c1 in BasicDataAccess.Data.Table1List on f.ID equals c1.fieldID
join fRes in BasicDataAccess.Data.Table2List on f.ID equals fRes.fieldID
join soilTst in BasicDataAccess.Data.Table3List on f.ID equals soilTst.fieldID
join modelRsNM in BasicDataAccess.Data.Table4List on c1.ID equals modelRsNM.YearID
join fA in BasicDataAccess.Data.Table5List on f.ID equals fA.fieldID into group1
from g1 in group1.Where(fA => fA.Year == reportYear).DefaultIfEmpty()
join nA in BasicDataAccess.Data.Table6List on f.ID equals nA.fieldID into group2
from g2 in group2.Where(nA => nA.Year == reportYear).DefaultIfEmpty()
where g1.sourceName == null && g2.sourceName == null
Issue: the query when executed throws Nullreference exception was unhandled..Object reference not set to an instance of an object error..
What am I missing? Is it possible to reference the left outer join table in where clause? Please help!

As far as I can see, this line
from g1 in group1.Where(fA => fA.Year == reportYear).DefaultIfEmpty()
can produce null if there's no rows. In this case, when you try to filter it (where g1.sourceName == null) you'll get null reference (because g1 is null).

Related

cast to value type 'System.Int32' failed because the materialized value is null

I have a Linq Query but it gives above error I guess due to NULL as I have Module,Block and semester as nullable int when semester column is having value than Module and Block would be null and when Module and block would be null than semster is having value How to handle the below query.
var test1 = (from c in db.StudentCoursesAssigned
join e in db.Years
on c.Year_Id equals e.Id into table1 from e in table1.DefaultIfEmpty()
join cc in db.Courses
on c.Course_Id equals cc.Course_Id into table2 from cc in table2.DefaultIfEmpty()
join g in db.grades
on c.Grade equals g.Id into table3 from g in table3.DefaultIfEmpty()
join m in db.Moduels
on c.Module_Id equals m.Id into table4 from m in table4.DefaultIfEmpty()
join p in db.Programs
on c.Program_Id equals p.Id into table5 from p in table5.DefaultIfEmpty()
join b in db.Blocks
on c.Block_Id equals b.Id into table6 from b in table6.DefaultIfEmpty()
join s in db.Semesters
on c.Semster_Id equals s.Semester_Id into table7 from s in table7.DefaultIfEmpty()
join ss in db.Students
on c.Student_id equals ss.Student_Id into table8 from ss in table8.DefaultIfEmpty()
select new
{
Student_Name=ss.Student_FName,
Course=cc.Course_Name,
Active=c.Active,
Course_start_date=c.Enrolment_Start,
Course_End_date=c.Enrolment_End,
Grade=g.Name,
Module=m.Name,
Program=p.Program_Title,
Year=e.Id,
Semester=s.Semester_Title,
blocks=b.Id
}).ToList();
That is the right Linq query which solves
var test1 = (from c in db.StudentCoursesAssigned
join e in db.Years
on c.Year_Id equals e.Id into table1 from e in table1.DefaultIfEmpty()
join cc in db.Courses
on c.Course_Id equals cc.Course_Id into table2 from cc in table2.DefaultIfEmpty()
join g in db.grades
on c.Grade equals g.Id into table3 from g in table3.DefaultIfEmpty()
join m in db.Moduels
on c.Module_Id equals m.Id into table4 from m in table4.DefaultIfEmpty()
join p in db.Programs
on c.Program_Id equals p.Id into table5 from p in table5.DefaultIfEmpty()
join b in db.Blocks
on c.Block_Id equals b.Id into table6 from b in table6.DefaultIfEmpty()
join s in db.Semesters
on c.Semster_Id equals s.Semester_Id into table7 from s in table7.DefaultIfEmpty()
join ss in db.Students
on c.Student_id equals ss.Student_Id into table8 from ss in table8.DefaultIfEmpty()
select new
{
Student_Name = ss.Student_FName == null ? "No Value" : ss.Student_FName,
Course = cc.Course_Name == null ? "No Value" : cc.Course_Name,
Active = c.Active ,
Course_start_date = c.Enrolment_Start,
Course_End_date = c.Enrolment_End ,
Grade = g.Name == null ? "No Value" : g.Name,
Module = m.Name == null ? "No value" : m.Name,
Program=p.Program_Title == null ? "No Value" : p.Program_Title,
Year=e.Name,
Semester=s.Semester_Title == null ? "No Value" : s.Semester_Title,
blocks=b.Name == null ? "No Value":b.Name,
student_Id=ss.Student_Id,
id=c.Id,
}).ToList();
```

Why my Linq query gives wrong results

I have this SQL query which gives the output as 15.but, when I converted the same query in Linq,it gives an output as 72.
select sum(DATEDIFF(day,LeaveBreakup.StartDate,LeaveBreakup.EndDate)+1) as totalNoOfDays from LeaveApplication
inner join Employee
on LeaveApplication.Employee=Employee.Id
inner join Team
on Employee.Team=Team.Id
inner join LeaveBreakup
on LeaveApplication.Id=LeaveBreakup.LeaveApplication
inner join LeaveTypeDetail
on LeaveBreakup.LeaveType=LeaveTypeDetail.LeaveType
where Employee.Team=5 and LeaveStatus!=0 and LeaveBreakup.StartDate between '01-01-2016' and '01-31-2016' and LeaveBreakup.WhichHalf=0
var Stafflist = (from LApp in db.LeaveApplications
join Emp in db.Employees
on LApp.Employee equals Emp.Id
join Tm in db.Teams
on Emp.Team equals Tm.Id
join LBrk in db.LeaveBreakups
on LApp.Id equals LBrk.LeaveApplication
join LTD in db.LeaveTypeDetails
on LBrk.LeaveType equals LTD.LeaveType
where Emp.Team == 5 && LApp.LeaveStatus != 0 && LBrk.StartDate >= d1 && LBrk.StartDate <= d2 && LBrk.WhichHalf == 0
select DbFunctions.DiffMinutes(LBrk.StartDate, LBrk.EndDate)).Sum() / 60;

Linq left outer join and group by issue

Hi All my following query returns results like this:
lstView.DataSource = (from h in context.HolidayMains
join hd in context.HolidayDetails on h.Id equals hd.HolidayMainId into hd2
from hd in hd2.DefaultIfEmpty()
join e in context.Employees on h.CreatedBy equals e.Id into e2
from e in e2.DefaultIfEmpty()
join o in context.OfficeLocations on hd.OfficeLocation equals o.Id into o2
from o in o2.DefaultIfEmpty()
select new
{
h.HolidayTitle,
h.Date,
OfficeLocation = o.Name,
CreatedBy = e.Name,
h.Id
}).ToList();
But I need result like this :
How it can be done?

Linq Left outer join replace null values returned

I am sure this has been discussed before but I read several LINQ left outer join posts and couldn't figure out whether it has been discussed or not. The closest thread that matched what I was looking for is Replace returned null values in LEFT OUTER JOIN, but its not LINQ related.
Now on to my question, my query does left outer join with DefaultIfEmpty(). Here's an example query I grabbed from another post for illustration
from adx_event in Adx_eventSet
join adx_eventsponsor in adx_eventsponsor_eventSet
on adx_event.Adx_eventId equals adx_eventsponsor.adx_eventid into j
from adx_eventsponsor in j.DefaultIfEmpty()
select new
{
Name = adx_event.Name,
Name = adx_eventsponsor != null ? adx_eventsponsor.Name : null
};
In the above query, if adx_eventsponsor returns null, then the check "on adx_event.Adx_eventId equals adx_eventsponsor.adx_eventid into j" is failing with Null reference exception. How to handle this issue?
Here's the query I am working with, sorry its a lengthy one with 5 left joins
from t1 in table1List
join t2 in table2List on t1.ID equals t2.fID
join m in DataAccess.Data.table3List on t2.ID equals m.ID into fg
from fgi in fg.Where(m => m.Year == reportYear).DefaultIfEmpty()
join c1 in table4List on t2.ID equals c1.ID into t4
from c1 in t4.Where(c1 => c1.Year == reportYear && c1 != null).DefaultIfEmpty()
join c2 in table4List on t2.ID equals c2.ID into t5
from c2 in t5.Where(c2 => c2.Year == reportYear - 1).DefaultIfEmpty()
join fA in table5List on t2.ID equals fA.ID into t6
from fA in t6.Where(fA => fA.Year == reportYear).DefaultIfEmpty()
join src in table6List on new { ID = fA != null ? fA.sourceID :
new Guid(" {ccae20792ebc-4200-879d-866fc82e6afa}"), Year = reportYear } equals new
{ ID = Src.ID, Year = Src.Year } into t7 from Src in t7.DefaultIfEmpty()
My question is in the last left outer join where if fA (from table5List) returns null, I can't do a join on fA.sourceID, so I am explicitly hardcoding a Guid to avoid that null exception. What is a better way to do this?
Thanks for your help!

join on subquery results

I've got a table called IssueStatuses and another table called Issues. Issues has a StatusID and SubStatusID, both of which are from the IssueStatuses table which has an additional field that states if it's a SubStatus or not, like so:
IssueStatuses
IssueStatusID
IssueStatus
IsSubStatus
I'm trying to get a list of SubStatuses for a particular list of Issues. In SQL it's:
SELECT iss.IssueStatus, COUNT(iss.IssueStatus) AS Total
FROM Issues AS Issues
INNER JOIN Rooms r ON Issues.RoomID = r.RoomID
INNER JOIN Locations l ON l.LocationID = r.LocationID
INNER JOIN Customers c ON l.CustomerID = c.CustomerID
INNER JOIN (SELECT * FROM IssueStatuses WHERE IsSubStatus = 0) ist ON Issues.IssueStatusID = ist.IssueStatusID
INNER JOIN (SELECT * FROM IssueStatuses WHERE IsSubStatus = 1) iss ON Issues.IssueSubStatusID = iss.IssueStatusID
WHERE c.Customer = 'ABC'
AND l.Location = 'MySite'
GROUP BY iss.IssueStatus
but I"m having trouble converting it to LINQ. The desired output would be something like:
IssueStatus | Total
-------------------
Open 15
Delayed 25
On Time 8
Here's what I've tried with LINQ:
var query = from i in Issues
join r in Rooms on i.RoomID equals r.RoomID
join l in Locations on r.RoomID equals l.LocationID
join c in Customers on l.CustomerID equals c.CustomerID
where i.IssueStatusID == (from ist in IssueStatuses
where ist.IsSubStatus == false
select ist)
&& i.IssueSubStatusID == (from iss in IssueStatuses
where iss.IsSubStatus == true
select iss)
&& c.Custome == "ABC"
&& l.Location == "MySite"
group i by i.IssueStatus
but I know it's wrong because LINQPad throws an error stating:
can't convert int to type Models.IssueStatus
What I need to do is use iss.IssueStaus to group on but I can't access it. Can someone tell me what I'm doing wrong?
How about this (untested but I should be close):
var query = from i in Issues
join r in Rooms on i.RoomID equals r.RoomID
join l in Locations on r.LocationID equals l.LocationID
join c in Customers on l.CustomerID equals c.CustomerID
join ist in IssueStatuses on i.IssueStatusID equals ist.IssueStatusID
join iss in IssueStatuses on i.IssueSubStatusID equals iss.IssueStatusID
where !ist.IsSubStatus && iss.IsSubStatus
&& c.Customer == "ABC"
&& l.Location == "MySite"
group i by iss.IssueStatus into g
select new {IssueStatus = g.Key, Total = g.Count()}
Your two inner from statements return objects and not IDs ... select the ID you need like ist.IssueStatusID:
var query = from i in Issues
join r in Rooms on i.RoomID equals r.RoomID
join l in Locations on r.RoomID equals l.LocationID
join c in Customers on l.CustomerID equals c.CustomerID
where (from ist in IssueStatuses
where ist.IsSubStatus == false
select ist.IssueStatusID).Contains(i.IssusStatusID)
&& (from iss in IssueStatuses
where iss.IsSubStatus == true
select iss.IssueStatusID).Contains(i.IssueSubStatusID)
&& c.Customer == "ABC"
&& l.Location == "MySite"
group i by i.IssueStatus

Resources