【问题标题】:Multiple Join with Linq to Entity使用 Linq 多连接到实体
【发布时间】: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


【解决方案1】:

我建议使用查询语法(如果您不能使用导航属性)

使用此语法,您的第一个查询看起来会非常相似

var query =
   from t1 in RepoTable1.AsQueryable()
   join t2 in RepoTable2.AsQueryable() on t1.Id equals t2.Id into t2g
   from t2 in t2g.DefaultIfEmpty() //DefaultIfEmpty is used for left joins
   join t3 in RepoTable3.AsQueryable() on t2.Id equals t3.Id
   select new 
   {
    t1, t2, t3
   };

【讨论】:

  • 太完美了,谢谢。我使用了 IQueryable 类型的变量“查询”而不是 RepoTable1.AsQueryable()。但是现在我不需要将我的 Linq-to-Entity 查询与新的 Linq-to-SQL 查询“合并”。试着去做,但如果你有任何建议......
猜你喜欢
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多