LINQ multiple joins with multiple conditions - c#

I have few large tables and I need to join them. In SQL it looks like:
select * from dbo.Table1 t1
join dbo.Table1 t1Parent on t1.ParentId = t1Parent.Id
join dbo.MappingT1T3 t2 on t1Parent.Id = t2.ExternalId and t2.[Type] = 1
join dbo.Table3 t3 on t2.ForeignId = t3 .Id
where t1.[Type] = 3
Tried to convert this query to a such LINQ:
from t1 in dbo.Table1
join t1Parent in dbo.Table1 on t1.ParentId equals t1Parent.Id
join t2 in dbo.MappingT1T3 on new { Id = t1Parent.Id, [Type] = (int)1 } equals new { Id = t2.ExternalId, [Type] = (int)t2.[Type] }
join t3 in dbo.Table3 on t2.ForeignId equals t3.Id
where t1.[Type] == 3;
But seems execution plan differs a lot. Profile says that it tries to load all tables without conditions..

Try putting the constant to a seperate condition...
from t1 in dbo.Table1
where t1.[Type] == 3 // <--- PUT THIS ONE HIGHER
join t1Parent in dbo.Table1 on t1.ParentId equals t1Parent.Id
join t2 in dbo.MappingT1T3 on t1Parent.Id equals Id = t2.ExternalId
where (int)t2.[Type] == 1 // <--- SEPARATE CONDITION
join t3 in dbo.Table3 on t2.ForeignId equals t3.Id;

Related

How to apply Right Outer Join using LINQ in C#?

I am facing issue to apply Right Outer Join in LINQ. I am trying to build the similar query in LINQ by converting from SQL query.
My correct SQL query
select *
from Table1 t1
inner join Table2 t2 on t1.Id = t2.FID and t1.CID = 20
right outer join Table3 t3 on t1.GID = t3.GID
var result = from t1 in Table1
join t2 in Table2
on t1.ID equals t2.FID into gr1
where t1.CID = 20
join t3 in Table3
on t1.GID equals t3.GID into gr2
from t3 in gr2.DefaultIfEmpty()
select new Details (){
}
return result.ToList();
}
My LINQ query is not working as expected to SQL query.
This is also discussed here
how to make a right join using LINQ to SQL & C#
var RightJoin = from adds in dc.EmpresaAddendas
join cats in CatAddendas
on adds.IDAddenda equals cats.IDAddenda into joined
from cats in joined.DefaultIfEmpty()
select new
{
Id = cats.IDAddenda,
Description = cats.Descripcion
};
Try this:
var result = from t1 in Table1
join t2 in Table2
on new { id = t1.ID; cid = t1.CID } equals new { id = t2.FID: cid = 20} into gr1
join t3 in Table3
on t1.GID equals t3.GID into gr2
from t123 in gr2.DefaultIfEmpty()
select new Details (){
}
return result.ToList();
}
As you're discovered, most LINQ providers don't offer support for a right join. DefaultIfEmpty translates into a LEFT join. As a result, you need to flip the logic of your query around a bit to turn the right join into a left one.
As far as the actual syntax, I've had success adopting more of an ANSI-82 syntax rather than worrying about the into temp2 from temp3 in temp2 syntax. Something along the lines of:
var result =
from t3 in Table3
from t1 in Table1.Where(temp1 => temp1.GID == t3.GID).DefaultIfEmpty()
join t2 in Table2 on t1ID equals t2.FID
where t1.CID == 20
select new Details{};

SQL to LINQ - Left Join two conditions

How can I convert this outer left join to LINQ?
SELECT * from table1 t1
left join table2 t2 on t1.code = t2.code AND t2.id ='xxxxx'
WHERE t1.someId = 2
I'm trying something like this:
from t1 in db.table1
join t2 in db.table2 on t1.Code equals t2.Code
into oj
from sub in oj.DefaultIfEmpty()
where t1.someId == 2
where (sub.id == 'xxxx')
but not all rows from left table are being returned. The where clauses i think are applied after the join.
var res=(from t1 in table1.Where(x=>x.someId==2)
join t2 in table2.Where(y=>y.id==xxxx)
on t1.code = t2.code
into r
from t3 in r.DefaultIfEmpty()
select new {t1,t3}).ToList();

Multiple joins and logical operators

I would need some guidance to convert this query in LINQ (method-based or expression syntax):
SELECT * from table1 t1
JOIN table2 t2 ON t1.fieldA = t2.fieldA and t1.fieldB = t2.fieldB
JOIN table3 t3 ON t2.fieldC = t3.fieldA
WHERE
t3.Enabled=1 and
t2.Active = 1 and
t1.Linked=1;
Using expression syntax it seems logical operators are not supported in the join clause.
My failed attempt:
var query = from t1 in context.table1
join t2 in context.table2 on t1.fieldA equals t2.fieldB && t1.fieldB equals t2.fieldB
join t3 in context.table3 on t3.fieldA equals t3.fieldC
where
t1.Enabled == 1 && t2.Active == 1 && t3.Linked == 1;
EF does not support multiple objects to be used for joining, instead, you can create object that will contain all properties you want to apply equals on:
var query = from t1 in context.table1
join t2 in context.table2 on new {t1.fieldA, t1.fieldB} equals new {t2.fieldA, t2.fieldB}
join t3 in context.table3 on t3.fieldA equals t3.fieldC
where
t1.Enabled == 1 && t2.Active == 1 && t3.Linked == 1 ...
you code has wrong third condition
instead of
join t3 in context.table3 on t3.fieldA equals t3.fieldC
put
join t3 in context.table3 on t2.fieldC equals t3.fieldA

c# I need to perform this SQL Select to LINQ

I have this Select:
SELECT (MyFields)
FROM table1 T1
INNER JOIN table2 t2 ON t2.ID_t2 = T1.ID_T1
INNER JOIN
table3 t3 on t3.ID_t3=T1.ID_T1 and Left(t3.Other_t3_field,5)=t2.Another_t2_field
WHERE (Conditions)
Then, I tried in C#:
var query = from T1 in table1
join t2 in table2 on T1.ID_T1 equals t2.ID_t2
join t3 in **table3** on T1.ID_T1 equals v.ID_t3
join t4 in **table3** on t2.Other_t2_field equals Microsoft.VisualBasic.Strings.Left(t2.Another_t3_field, 5)
where (Conditions)
select new
{
(My fields)
};
Both works, but my C# query have more results then SQL Select, I don't know what I am doing wrong?
Well I'd start by changing the join on table 3 in the C# - use an anonymous type to join on multiple fields:
join t3 in table3 on new { Id = t1.ID_T1, X = t2.AnotherT2Field.Substring(0, 5) }
equals new { Id = t3.ID_T3, X = t3.OtherT3Field.Substring(0, 5) }
(I'd hope you can use Substring instead of Left here... it's much more idiomatic C#.)
You can add multiple join conditions with an anonymous type:
var query = from T1 in table1
join t2 in table2 on T1.ID_T1 equals t2.ID_t2
join t3 in **table3** on new {
ID = T1.ID_T1,
substring = t2.Other_t2_field
} equals new
{
ID = v.ID_t3,
substring = Microsoft.VisualBasic.Strings.Left(t2.Another_t3_field, 5)
}
where (Conditions)
select new
{
(My fields)
};
As Jon Skeet mentioned: you can also use Substring instead of Left.

Join 4 tables in DB with Stored Procedure?

in my database there is a table has 3 FK to other 3 tables i want to select the data in this table + data in the other 3 tables when the FK value = the PK values in the other tables
SELECT *
FROM t1
JOIN t2
ON t2.id = t1.t2_id
JOIN t3
ON t3.id = t1.t3_id
JOIN t4
ON t4.id = t1.t4_id
SELECT t1.Field1, t2.Field2, t3.Field3, t4.Field4
FROM Table t1
INNER JOIN Table2 t2 ON t1.ID = t2.ID
INNER JOIN Table3 t3 ON t1.ID = t3.ID
INNER JOIN Table4 t4 ON t1.ID = t4.ID
If there aren't always matching rows in Tables 2 - 4, and you want those records return still then change the INNER JOINs to LEFT JOIN
SELECT * FROM ParentTable as pt
LEFT JOIN table1 as t1
ON pt.t1_ID = t1.ID
LEFT JOIN table2 as t2
ON pt.t2_ID= t2.ID
LEFT JOIN table3 as t3
ON pt.t3_ID= t3.ID
This will return a record even if there are not matches in table1,2 or 3. #Ada and #Q's will exclude those records.
SELECT * FROM TBL1 T1
RIGHT JOIN TBL2 T2
ON T1.id = T2.id
RGIHT JOIN TBL3 T3
ON T3.id = T2.id
This will return all the records from Right table and matching records from Left table.

Categories