【发布时间】:2015-10-28 21:02:24
【问题描述】:
我想将以下 SQL 查询写入 Linq To Entity 查询。
SELECT *
FROM Table1
LEFT JOIN Table2 ON Table2.IdTable1 = Table1.Id
INNER JOIN Table3 ON Table3.IdTable2 = Table2.Id
SELECT *
FROM Table1
LEFT JOIN Table2 ON Table2.IdTable1 = Table1.Id
LEFT JOIN Table3 ON Table3.IdTable2 = Table2.Id
WHERE Table3.Id IS NULL
对于第一个,我正在研究这个: var query = RepoTable1.AsQueryable(); [一些查询 = query.Where(...)
query = query
.Join(RepoTable2.AsQueryable(), e => e.IdTable1, i => i.Id, (i, e) => i)
.GroupJoin(RepoTable3.AsQueryable(), c => c.IdTable2, eq => eq.Id, (eq, c) => eq);
关于加入,我有一些不明白的地方。 实际上,“eq => eq.Id”应该是“Table2”类型,但它是“Table1”。 如果我将“(i,e)=> i”更改为“(i,e)=> e”,则会出现编译错误,因为“查询”正在等待“Table1”类型。
对于第二个查询,我不知道如何将“Where()”添加到 Join 中(实际上,我主要是使用第一个)
提前致谢!如果这还不够清楚,请告诉我!
最终答案:
query = (from t1 in query
join t2 in RepoTable2.AsQueryable() on t1.Id equals t2.IdTable1 into joint1t2
from t2 in joint1t2.DefaultIfEmpty() // DefaultIfEmpty is used for left joins
join t3 in RepoTable3.AsQueryable() on t2.Id equals t3.IdT
select t1);
对于第二个查询:
query = (from t1 in query
join t2 in RepoTable2.AsQueryable() on t1.Id equals t2.IdTable1 into joint1t2
from t2 in joint1t2.DefaultIfEmpty() // DefaultIfEmpty is used for left joins
join t3 in RepoTable3.AsQueryable() on t2.Id equals t3.IdTable2 into joint2t3
from t3 in joint2t3.DefaultIfEmpty() // DefaultIfEmpty is used for left joins
where t3.Id== null
select t1);
【问题讨论】:
-
我讨厌 LINQ 中的左连接,但我可以为您解释其中的一些内容。
(i,e)应该是(e,i),基于您之前使用e来引用表 1 和i来引用表 2。接下来是您不应该分解查询,因为最终返回不(不应该?)只是 table1 中包含的记录,或者您需要将查询的第二部分的结果放入不同的变量。换个角度想,ReportTable1.AsQueryable()返回IQueryable<ReportTable1>,你的最终查询不应该返回那个。 -
您的最终查询应该返回一些匿名类型的 IQueryable,其中包括 table1、table2 和 table3 中的所有字段。
-
我倾向于发现 Linq 中连接的方法语法是最难写的东西之一。您是否尝试过用查询语法编写它?生成的查询语法与您已有的 SQL 非常相似。
-
联接很好,但丑陋的是左联接。如果 Join 只需要一个额外的 lamda 来填写您想要返回的内容(如果没有匹配项),我会更喜欢。像
.Join(Inner, OuterKey, InnerKey, MatchLamda, LeftOnlyLamda, RightOnlyLamda)这样的东西像Table1.Join(Table2, t1=>t1.id, t2=>t2.id, (t1,t2)=>new {Name=t1.Name,Address=t2.Address}, (t1,t2)=>new {Name=t1.Name,Address=null}, (t1,t2)=>new {Name=null,Address=t2.Address})一样用于完全外连接。 -
避免在 LINQ(到实体)中使用显式连接。始终尝试使用导航属性。
标签: sql-server linq join linq-to-entities inner-join