【问题标题】:LINQ: Combine join with left joinLINQ:将联接与左联接结合起来
【发布时间】:2016-11-11 18:21:03
【问题描述】:

假设我在 SQL 中有这个查询:

SELECT
    ....
FROM
   TableA a
   JOIN TableB b on a.Id = b.Id

我已经把它作为一个 linq 查询工作得很好:

var results = (from a in db.TableA 
               join b in db.TableB on a.Id equals b.Id
               select new MyObject {...}).ToList();

但现在我也想在组合中添加一个左连接。在 SQL 中:

SELECT
    ....
FROM
   TableA a
   JOIN TableB b on a.Id = b.Id
   LEFT JOIN TableC c on a.Id2 = c.Id2

我不确定如何在 linq 查询中处理这个问题。

【问题讨论】:

  • 在你的tableB加入后加一行join c in db.TableC on a.Id equals c.Id
  • 即使 TableC 现在有匹配的记录(c.ID2 为空),它的行为是否类似于 LEFT JOIN 并包含 TableA 中的所有行?
  • 你知道怎么写left outer join in LINQ,不是吗?就像查询中没有其他联接一样编写它,例如join c in TableC on a.Id2 equals c.Id2 into ac from c in ac.DefaultIfEmpty()
  • 你必须选择它MyObject
  • 和往常一样,首先看看您可以设置哪些导航属性而不是使用连接(TableA.TableBs 等)。

标签: c# sql asp.net linq


【解决方案1】:

SQL 的LEFT JOIN 概念是一个相当笨拙的抽象,当您考虑您真正想要做什么时。对于每个 TableA 条目,您真的希望有一个与之关联的 TableC 项目列表,对吗?

LINQ 使用一种更简单 (IMO) 的方式来表示这种抽象,因为它具有嵌套、分层对象的概念。提供者将生成一个 LEFT JOIN,但它也会将结果构建到一个易于使用的对象结构中。

var results = (from a in db.TableA 
               join b in db.TableB on a.Id equals b.Id
               select new MyObject {
                  ...
                  TableCEntries = 
                      from c in db.TableC
                      where c.Id == a.Id
                      select c     // or select specific values from c
               }).ToList();

如果你真的希望你的结果像左外连接那样变平,你可以这样做:

var results = (from a in db.TableA 
               join b in db.TableB on a.Id equals b.Id
               from c in db.TableC
               where c.Id == a.Id
               select new MyObject {
                  ...
               }).ToList();

...但是您不会得到任何 TableA 的条目,而 TableC 没有条目。对于这种行为,您必须使用group by/DefaultIfEmpty 做一些丑陋的事情,如Ivan Stoev's link 所示。

【讨论】:

  • 这并不等同于 SQL LEFT OUTER JOIN
  • 我看到了(并且大体上同意),但对于原始 OP 查询(a 和 b 之间的连接)也可以这样说。连接和组连接之间的选择取决于查询编写器。 Gert Arnold 的评论更有意义。只是一个想法 :) 顺便说一句,最后一次编辑不正确(where c.Id == a.Id) - 请参阅我在帖子下的评论。
  • 对于第二个 linq 查询,sql profiler 查询是什么样的?
  • @BlueLamp82:我不知道,你必须测试一下。但我猜它看起来像一个内连接,然后是一个左连接,带有一个 WHERE 子句。为什么要问?
猜你喜欢
  • 2021-09-28
  • 2016-03-04
  • 1970-01-01
  • 2010-10-14
  • 2016-12-13
  • 2014-02-06
  • 2023-03-20
  • 1970-01-01
  • 2011-01-18
相关资源
最近更新 更多