How to join table with multiple columns in linq? - c#

I have following code in linq, what I am trying to do is joining tables with multiple columns of one table
//NOT A VALID CODE
from t1 in table1
join t2 in table2 on ((t1.ID equals t2.orderId) || (t1.ID equals t2.pickupId ))// how can I do this
...
...
How can I achieve this in Linq?

Use an anonymous type
from t1 in table1
join t2 in table2 on new { t1.ID, t1.pickupId } equals new { t2.ID, t2.pickupId }
...

var query = from t1 in table1
from t2 in table2
where t1.ID == t2.orderId || t1.ID == t2.pickupId
select new { t1, t2};

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{};

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.

need to retrieve result set of Join Query

Need to retrieve result set of both tables but i am getting null value in it
var Items = from t1 in dbModal.Table1
join t2 in dbModal.Table2 on t1.id equals t2.Id
select new
{ t1, t2.column };
need to map above query like this
Select t1.*,t2.Column from T1
join T2 on T1.id=T2.Id

Join Two DataTables (Some Rows Match some Don't)

I have two Data Tables: T1 and T2
T1 and T2 both have a Column Registration, but T2 doesn't have all the same Rows as T1.
I have to combine the Two Tables such that if the Registration Number is same get columns from T2, if not show Blank, but I need ALL ROWS FROM T1, (IF MATCH OR NOT).
I tried this but I only get matching Rows:
var results = from table1 in T1
join table2 in T2
on (String)table1["Registration"] equals (String)table2["Registration"]
select new
{
Registration = (String)table1["Registration"],
DistanceInKM = (decimal)table1["DistanceInKM"],
TotalDistanceTravelledKM = (Double)table2["TotalDistanceTravelledKM"]
};
You're performing an inner join, which only shows rows that exist on both sides.
Try using a left outer join instead:
var results = (from table1 in T1.AsEnumerable()
join tmp in T2.AsEnumerable() on table1["Registration"] equals tmp["Registration"] into grp
from table2 in grp.DefaultIfEmpty()
select new
{
Registration = (String)table1["Registration"],
DistanceInKM = (decimal)table1["DistanceInKM"],
TotalDistanceTravelledKM = (table2 == null ? (double?)null : (Double)table2["TotalDistanceTravelledKM"])
};

How to rewrite this linq query correctly?

int id =2 ;
(from t1 in Table1
join t2 in Table2
on new { t1.id, id} equals new { t2.id, t2.otherid }
select t1).ToList();
Currently the above query gives me a compilation error saying
The type on one of the join expressions is incorrect.
As you can see in the above query I want to join on a single integer value as you would in sql. I want to these so that query is faster and I don't want to do a where at the end because that would mean it will get all the rows and then filter with the where clause. As I have lot of rows in both the tables it would be good if I can filter rows on join clause itself. Thanks for your help !
You need to use the same anonymous type (with the same property names) in both halves of the join:
on new { t1.id, otherId = 2 } equals new { t2.id, t2.otherId }
Your text implies that you actually want to join on a single value; if so, you don't need an anonymous type at all:
on t1.id equals t2.otherid
When you join using an anonymous classes, the members of those class' names must match. The problem is easily solved by adding names to your anonymous class' members:
int id = 2;
(from t1 in Table1
join t2 in Table2
on new { Id = t1.id, OtherId = id }
equals new { Id = t2.id, OtherId = t2.otherid }
select t1).ToList();
Although, the more I look at it the more I realize that the join doesn't need to be that complex. It looks like you're adding the static id in the join. You should be able to get away with it in the where clause which would reduce the join to a single value:
int id = 2;
(from t1 in Table1
from t2 in Table2
on t1.id equals t2.id
where t2.otherid = id
select t1).ToList();
I see two possible solutions:
This variant prefilters Table2, then performs the join.
int id =2;
(from t1 in Table1
join t2 in (from a in Table2 where a.otherid == id select a)
on t1.id equals t2.id
select t1).ToList();
Here is a debugged variant of your original code. Because the compiler uses the property names when creating anonymous objects, you have to be explicit about the names.
int id =2;
(from t1 in Table1
join t2 in Table2
on new { Id1 = t1.id, Id2 = id } equals new { Id1 = t2.id, Id2 = t2.otherid }
select t1).ToList();
HTH, Mark

Categories