Left Join 2 tables with main table using LINQ - c#

This is my Query in SQL :
Select distinct * from tr.Table1
Left Outer join tr.Table2 on tr.Table1.ID = tr.Table2.ID
Left Outer join tr.Table3 on tr.Table2.AId= tr.Table3.ID
where tr.Table1.Deleted =1 and tr.Table1.Ready=1 and tr.Table1.Show=0
The query is working in SQL and gives the expected results.The thing here is that I want the equivalent of this using LINQ. I have tried some variations in LINQ queries such as :
var query = from p in _ctx.Table1
join s in _ctx.Table2 on p.Id equals s.Id into bag1
from to in bag1.DefaultIfEmpty()
join tx in _ctx.Table3 on to.AId equals tx.Id into bag2
from ts in bag2.DefaultIfEmpty()
select new
{
ContactNo = to.Table1.ContactNo
};
But it always doesn't return all the field values. Some are returned as NULL. Also tried referring to some other link as well but they all focus on joining with the parent table whereas I have to join one of the joined tables with the other one. So here I am, struggling with this.
This is the output that I'm getting as of now. Some values are null. The field has values but due to some joining issue, they are returned as NULL.
Guidance here is appreciated. Thank you.

Your query looks fine to me, the reason why you must be getting the Nulls is because when we use DefaultIfEmpty, it returns null for non-matching rows, thus you need to handle that while fetching the actual results. Try doing something like this:-
var query = from p in _ctx.Table1
join s in _ctx.Table2 on p.Id equals s.Id into bag1
from to in bag1.DefaultIfEmpty()
join tx in _ctx.Table3 on to.AId equals tx.Id into bag2
from ts in bag2.DefaultIfEmpty()
select new
{
ContactNo = to == null ? String.Empty : to.Table1.ContactNo
};
Assuming, ContactNo to be of type String, I have used String.Empty you can use any default value.

Related

Linq Sql Int null equal to null. Not returning rows

I have a linq query with a where clause as below
var ExistingGroupDataSource = (from ppatg in dbContext.XXXXXXXXX
join pd1 in dbContext.XXXXXXXXXXX on ppatg.ScheduleID equals pd1.ScheduleID
where pd1.GroupID == null
select
new
{
FinishPDI = pd1.ProductionDateID,
FinishingDate = pd1.WorkFlowDate,
ppatg.GroupName,
ppatg.PNTGroupID
});
In the database GroupID is an int that can be null. The linq query returns rows without the filtered where clause but none when I include the where clause. There are null values in the GroupId column in the database.
It is definitely this statement that produces no results. All the literature on the subject online says that this is equivalent to
pd1.GroupID is null // in sql
I am getting results that contradict this
Sql code is
select pd1.ProductionDateID as FinishPDI, pd1.WorkflowDate as FinishingDate,GroupName ,PNTGroupId
from XXXXXXXXXXXX
inner join XXXXXXXXXXXX pd1 on
XXXXXXXXXXXX.ScheduleId = pd1.ScheduleID
where pd1.GroupID is null
You can combine your where with the join, which should give you the expected results:
var ExistingGroupDataSource = (from ppatg in dbContext.XXXXXXXXX
join pd1 in dbContext.XXXXXXXXXXX.Where(p => !p.GroupId.HasValue) on ppatg.ScheduleID equals pd1.ScheduleID
select
new
{
FinishPDI = pd1.ProductionDateID,
FinishingDate = pd1.WorkFlowDate,
ppatg.GroupName,
ppatg.PNTGroupID
});

.NET SQL Query joining two different tables

I'm brand new to .net MVC, and while I have some basic experience with writing SQL queries, I'm not sure how to go about what I need to do for .NET.
My initial query looks like this:
var results = (from s in db.Members
join sa in db.FocusArea on s.ID equals sa.MemberID
where sa.Area == SearchString
select new { s.ID, s.Name, s.Overview }).ToList();
This is not functioning correctly. It is seaching in the s.Overview for some reason. And, I need to make this query much more complicated. In short, I have three tables I need to search across. And with this query, it is not working:
var conceptResults = (from s in db.Cohorts
join oa in db.OutcomeArea on s.ID equals oa.CohortID
where ((oa.Area.Contains(SearchString))
|| (oa.OutcomeType.Contains(SearchString)))
select new { s.ID, s.Name, s.Overview }).ToList();
I need to use my SearchString to search for matches in both Area and Description in db.FocusArea.
I also need to use my SearchString to search for matches (contains) in another table db.SpecificFocusAreas for column SFocusArea where again the join is the ID/MemberID.
Is there a way to essentially do a join or join type of statement? I don't want to join all three tables because I am looking for results from either of the two joins, not from all joins.

Using Left Outer Join in Linq

I want to write one LINQ query with left outer join.For this I am able to write the corresponding SQL query which returns the desired output but the same in linq doesn't work for me.
This what my SQL looks like:
SELECT Table1.ID, Table1.Description
FROM Table1 LEFT OUTER JOIN
Table2 ON Table1.AID = Table2.AID AND Table1.TID = Table2.TID
WHERE (Table2.Status <> 'Using') OR (Table.Status IS NULL)
This query returns 7 records for me and that is what my requirement is.Now the same query I want to write with LINQ and this is what I tried with:
return (from t1 in db.Table1.AsEnumerable()
join t2 in db.Table2.AsEnumerable() on t1.AID equals t2.AID into outer
from item in outer.DefaultIfEmpty()
where item.TID == t1.TID
&& string.IsNullOrEmpty(item.Status) || item.Status != "Using"
select t1
);
But I have been facing issues with this.Here , it is not able to find item and thus returning
'Object reference not set to an instance of an object.'
What am I doing wrong over here????
I have been trying continuously but ended up with no solutions . So, any help in this would be highly appreciated.Thanks in advance..
Your SQL and LINQ statement are not the same, you have a different join clause.
Try this:
from t1 in db.Table1
join t2 in db.Table2 on new {
aID = t1.AID,
tID = t2.TID
}
equals new {
aID = t2.AID,
tID = t2.TID
} into outer
from item in outer.DefaultIfEmpty()
where item.Status == null || item.Status != "Using"
select t1
You can add multipe join relations with the new {} equals new {} statement.
DefaultIfEmpty returns a collection containing a single, default item if there is nothing in the collection.
As your entities are probably classes rather than structs, that means you get a collection with a single null in it, not a collection with a single item in it with null fields.
As well as the join clause change suggested by Loetn, you should also change your where condition to
where item == null || item.Status != "Using"

Linq Join variable scoping issue

Really odd issue that I cant work out.
I am trying to join two tables in a linq statement to only retrieve records where the record in table 1 has no related rows in table 2.
I have used Joins before but for some reason I cant get VS to recognise the second table in the linq statement.
EG.
var result =
(from pc in _dataSource.Payments
join bc in _dataSource.BouncedCheques
on pc.PaymentID != bc.PaymentID //This is where the error occurs, VS does not recognise "bc"
where pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
orderby pc.PaymentDate descending
select new PaymentAllocation
{
PaymentId = pc.PaymentID,
PaymentDate = pc.PaymentDate,
CustomerNumber = pc.CustomerNumber,
ChequeReference = pc.ChequeReference,
PaymentValue = pc.PaymentValue,
AllocatedValue = pc.AllocatedValue,
UnallocatedValue = pc.PaymentValue - pc.AllocatedValue,
ReceivedBy = pc.ReceivedBy,
PaymentType = pc.PaymentType,
PostedDate = pc.PostedDate
});
Basically the problem is that the variable "bc" does not seem to be recognised, however I have several other similar Linq queries that all work well
Any ideas?
Your problem is that the syntax for join uses the keyword equals and not standard boolean operators.
Try replacing your join by a cartesian product of your tables:
from pc in _dataSource.Payments
from bc in _dataSource.BouncedCheques
where
pc.PaymentID != bc.PaymentID
&& pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
In the join clause you should use the equals keyword:
try:
on pc.PaymentID equals bc.PaymentID

LINQ and various joining sample

i just learning LINQ. so first of all i need to be familiar with join with linq. i search google for left outer and right outer join with linq and i got answer like
left outer join
var LeftJoin = from emp in ListOfEmployees
join dept in ListOfDepartment
on emp.DeptID equals dept.ID into JoinedEmpDept
from dept in JoinedEmpDept.DefaultIfEmpty()
select new
{
EmployeeName = emp.Name,
DepartmentName = dept != null ? dept.Name : null
};
right outer join
var RightJoin = from dept in ListOfDepartment
join employee in ListOfEmployees
on dept.ID equals employee.DeptID into joinDeptEmp
from employee in joinDeptEmp.DefaultIfEmpty()
select new
{
EmployeeName = employee != null ? employee.Name : null,
DepartmentName = dept.Name
};
from then code i just could not understand how it is left outer join because no left outer key word is use here. so please tell me how to understand that the join is left outer join or right outer.
when i will use linq then how like operator can be use. 'a%' or '%a' or '%a%'. i saw there is contain method which is bit different.
please discuss the two issue. thanks
The "join ... in ... on ... into" piece of LINQ query syntax, is translated into a GroupJoin().
GroupJoin() method, for each key in the outer list (or table), returns a list of elements in the inner list (or table) having the same key, or an empty list if such key doesn't exist.
Hence, the left outer join code of your question is clearer:
If JoinedEmpDept (i.e. the list of elements having the same key of the current examined outer list entry) is empty, dept is set to null (thanks to DefaultIfEmpty() method).
Translation in pseudo code:
for each employee in ListOfEmployees
get the list of dept having ID equal to empl.DeptID
and set them into JoinedEmpDept
then for each dept in JoinedEmpDept
(if empty iterates over a single null dept)
returns an new element containing:
employee.Name and dept.Name (or null if dept is null)
The right outer join instead, is basically a left outer join with outer and inner lists exchanged.
About the "like" question, you should use string.Contains("a") for '%a%', string.StartsWith("a") for 'a%', string.EndsWith("a") for '%a'
Example:
var query = from el in listOfStrings
where el.StartsWith("AB")
select el;
EDIT:
About the IN() operator question...
well, you can use Contains() also for that, or Any():
var inGroup = new []{ "Foo", "Bar" };
var query1 = from el in listOfStrings
where inGroup.Contains(el)
select el;
// or equally
var query2 = from el in listOfStrings
where inGroup.Any(x => el.Equals(x))
select el;
The left outer join is so because of this line:
from dept in JoinedEmpDept.DefaultIfEmpty()
which will get all of the employees, even if they are not in a department. The DefaultIfEmpty turns the join into an left outer join, when the SQL is generated.
See this blog post for more details: C#: Left outer joins with LINQ
Left join Tip,
Instead of:
from user in tblUsers
join compTmp1 in tblCompanies
on user.fkCompanyID equals compTmp1.pkCompanyID into compTmp2
from comp in compTmp2.DefaultIfEmpty()
You can write:
from user in tblUsers
from comp in tblCompanies.Where(c => c.pkCompanyID == user.fkCompanyID).DefaultIfEmpty()

Categories

Resources