How to convert the below SQL query into LINQ query for C#.net
Select t1.id,t2.Name
From table1 t1
INNER JOIN table t2
ON ((t1.column3 is null and t1.id = t2.id)
OR( t.Column3 is NOT NULL and t1.column3 = t3.Column3))
Join tblXYZ xyz on t1.column4 = xys.columnn2
I was unable to add or condition after first set up comparison in linq query, please suggest correct way to achieve this in linq.
Making some assumptions about what you meant, I would suggest hoisting the OR to a union:
(from t1 in table1
join t2 in table2 on t1.Column3 equals t2.Column3
join xyz in tblXYZ on t1.Column4 equals xyz.column2
where t1.Column3 != null).Union(
from t1 in table1
join t2 in table2 on t1.id == t2.id
join xyz in tblXYZ on t1.Column4 equals xyz.column2
where t1.Column3 == null)
Related
I've been tasked with converting some crusty old SQL to Linq2SQL and I know this shouldnt be the first choice however it needs to be done.
Problem
I'm stuck attempting to force specific joins to replicate the desired output and the following is a simplified version of the SQL with one parameter variant shown followed by a simplified version of my attempt in Linq2SQL. Several alternative fields may be queried in Table1 hence the use q and q2 in the converted code though the actual parameters are not relevant to the issue.
Aim
The query needs to retrieve relevant rows from Table1, the latest related row from Table2 and additional data from Table2's parent table Table3, preferably in a single pass.
There may be 0-n matches in Table1, Table1 has a 1:n relationship with Table2 with 0-n rows, there is a 1:n relationship between Table3 and Table2.
Regardless of how I structure the expressions, the linq generates an INNER JOIN onto Table2 excluding rows in Table1, how can I structure the linq query to achieve the desired result?
SELECT [...]
FROM Table1 t1
LEFT JOIN (
SELECT MAX(id) AS id, parent_id
FROM Table2
GROUP BY parent_id
) x2 ON t1.id = x2.parent_id
LEFT JOIN Table2 t2 ON x2.id = t2.id
LEFT JOIN Table3 t3 ON t2.table3_id = t3.id
WHERE t1.id = row_id
var q = dc.Table1.AsQueryable();
q = from r in q where r.id == row_id select r;
var q2 = from r in (q)
join x2 in (from r in dc.Table2.DefaultIfEmpty() group r by r.parent_id into maxt2 let max_id = maxt2.Max(f => f.id) select new { maxt2.Key, max_id }) on r.id equals wx.Key
join t2 in dc.Table2.DefaultIfEmpty() on x2.max_id equals t2.id
join t3 in dc.Table3.DefaultIfEmpty() on t2.table3_id equals t3.id
select
{
[...]
};
Here is my translation using my recipe rules:
var Q1 = from t2 in dc.Table2
group t2 by t2.parent_id into t2g
select new { parent_id = t2g.Key, id = t2g.Max(t2 => t2.id) };
var Q2 = from t1 in Table1
where t1.id == row_id
join q1 in Q1 on t1.id equals q1.parent_id into q1j
from q1 in q1j.DefaultIfEmpty()
join t2 in dc.Table2 on q1.id equals t2.id into t2j
from t2 in t2j.DefaultIfEmpty()
join t3 in dc.Table3 on t2.table3_id equals t3.id into t3j
from t3 in t3j.DefaultIfEmpty()
select new { t1, t2, t3 };
I need to join 5 tables in a query. 3 of these tables must have relations, but two of them are optionally connected to an entry.
Because of this, I am trying to do a LEFT JOIN to Table4 and Table5 like this:
var cDesc = (cDesc == null ? "" : cDesc);
var cStreet = (cStreet == null ? "" : cStreet);
var q = await (from t1 in MyContext.Table1
join t2 in MyContext.Table2
on t1.ID equals t2.ObjectID
join t3 in MyContext.Table3
on t2.TeamID equals t3.TeamID
join t4 in MyContext.Table4
on t1.ID equals t4.ObjectID
into join3
from j3 in join3.DefaultIfEmpty()
join t5 in MyContext.Table5
on j3.StorageID equals t5.StorageID
where t2.ObjectType.Equals(16)
&& t3.UserID.Equals(userID)
&& t1.Description.Contains(cDesc)
&& l.Address.Contains(cStreet)
orderby t1.ID descending
select new Table1ListModel
{
ID = t1.ID,
Description = t1.Description,
Address = t5.Address
}
)
.Take(takeThis)
.ToListAsync();
But this query only works for rows that has a connection to Table4, so I'm doing something wrong obviously.
Am I doing the join correctly? Or is the problem that I want to run a where on address that comes from the fifth table?
Basically once you left join one table into a query any additional tables that you want to join to that one should almost always also be done with left joins. In your case you're saying you want keep rows in Table1 that don't have a match in Table4, but then you say you only want matches between Table4 and Table5 which basically will remove all the Table1 results that didn't have a match in Table4. Basically you want something like this
from j3 in join3.DefaultIfEmpty()
join temp5 in MyContext.Table5
on j3.StorageID equals temp5.StorageID into join4
from t5 in join4.DefaultIfEmpty()
This looks like a source of your problem:
join t4 in MyContext.Table4
on t1.ID equals t4.ObjectID
into join3
This means that you are inner joining Table4 to Table1
How can I make a Linq To SQL join on multiple tables where 1 table should produce a Cartesian product.
To shed some more light, here is a sample of the SQL query.
SELECT Table1.MyField, Setup.SomeField
FROM Table1 INNER JOIN Table2 ON Table1.SomeField = Table2.SomeField, Setup
My Linq to SQL are like:
var q = from t1 in db.Table1
join t2 in db.Table2 on t1.SomeField equals t2.SomeField
join setup in db.Setup
select new {t1.MyField, setup.SomeField};
I'm getting an error on the last join that Type inference failed in the call to 'Join'.
Use SelectMany rather than a Join to perform a Cartesian Product.
In query syntax that would be:
var query = from t1 in db.Table1
from t2 in db.Table2
select new {t1, t2};
This will also do:
var q = from t1 in db.Table1
join t2 in db.Table2 on t1.SomeField equals t2.SomeField
from setup in db.Setup
select new {t1.MyField, setup.SomeField};
I want to rewrite this simple MS SQL Query in Linq To SQL:
SELECT * FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.ID = T2.Table1ID OR T1.FirstName = T2.FirstName
How do I rewrite this in Linq To SQL?
Try this, although I don't know how well Linq-to-SQL will translate it:
from t1 in ctx.Table1
from t2 in ctx.Table2
.Where(t => t1.ID == t.Table1ID ||
t1.FirstName == t.Firstname)
.DefaultIfEmpty()
select new {t1, t2}
I don't believe this can be done because I don't think you can do the OR part of the join. The way you do joins in L2S would be (roughly)
join .. on
new {
T1.ID,
T1.FirstName
} equals new {
T2.Table1ID,
T2.FirstName
}
but that would match both.
Only thing I can think you could do would be to do some sort of subquery in there. But that's probably not what you're looking for. Sklivvz's suggestion may be the best one.
This is an inner join.
from t1 in ctx.Table1
from t2 in ctx.Table2
where t1.ID == t2.Table1ID ||
t1.FirstName == t2.Firstname
select t1
To get a left join it looks like you use DefaultIfEmpty(), per MSDN.
from t1 in ctx.Table1
from t2 in ctx.Table2.DefaultIfEmpty()
where t1.ID == t2.Table1ID ||
t1.FirstName == t2.Firstname
select t1
I'm trying to do the following query in Linq
SELECT *
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.ID = T2.AnotherID
LEFT OUTER JOIN Table3 T3
on T1.ID = T3.AnotherID
It works as expected in proper SQL syntax, but i'm having a hard time translating it to the corresponding Linq to SQL syntax.
How do i combine left join with an inner join?
Regards,
var results = from t1 in Table1
from t2 in Table2
where t1.ID = t2.AnotherID
join t3 in Table3 on t1.ID equals t3.AnotherID into joined
from j in joined.DefaultIfEmpty()
select new {t1, t2, t3 = j}