LINQ在On子句中具有多个条件的联接


93

我正在尝试在LINQ中实现查询,该查询在ON子句中使用具有多个条件的左外部联接。

我将使用以下两个表的示例Project(ProjectID,ProjectName)和Task(TaskID,ProjectID,TaskName,已完成)。我想查看所有项目的完整列表以及它们各自的任务,但只能看到已完成的那些任务。

我无法使用过滤器,Completed == true因为这将过滤掉所有未完成任务的项目。相反,我想添加Completed == true到联接的ON子句中,以便显示完整的项目列表,但仅显示已完成的任务。没有完成任务的项目将显示一行,且Task的值为空。

这是查询的基础。

from t1 in Projects
join t2 in Tasks
on new { t1.ProjectID} equals new { t2.ProjectID } into j1
from j2 in j1.DefaultIfEmpty()
select new { t1.ProjectName, t2.TaskName }

如何添加&& t2.Completed == trueon子句?

我似乎找不到有关如何执行此操作的任何LINQ文档。


在这里使用Lambda语法的相关答案
StuartLC '18

Answers:


130

您只需要在两边将匿名属性命名为相同

on new { t1.ProjectID, SecondProperty = true } equals 
   new { t2.ProjectID, SecondProperty = t2.Completed } into j1

根据@svick的评论,这是另一个可能更有意义的实现:

from t1 in Projects
from t2 in Tasks.Where(x => t1.ProjectID == x.ProjectID && x.Completed == true)
                .DefaultIfEmpty()
select new { t1.ProjectName, t2.TaskName }

2
这似乎是一种不明显的方法。我不确定我会理解该怎么做。
svick

1
@svick-使用匿名类型可以让您加入多个条件。您只需要确保属性名称在两种类型上都匹配即可。不确定混乱来自何处?
Aducci 2011年

困惑在于,将两个相等性(而and不是某个“怪异”对象的一个​​相等性)结合在一起确实更有意义。为了证明我的观点,您的代码是错误的。为了工作,您必须true在左侧和t2.Complete右侧。
2011年

1
谢谢阿杜奇。我必须在查询中交换双方以获取正确的上下文,但这确实可行。这个问题得到了简化,在我的现实世界中,不仅仅是SecondProperty是true还是false,SecondProperty是一个整数,我使用AND SecondProperty IN (123, 456)。我将继续挑战,您所能提供的任何帮助将不胜感激。
Kuyenda

@svick-很好,我切换了t2.Completed真实值的顺序。我添加了另一个可能对您来说不那么奇怪的解决方案。
阿杜奇(Aducci)2011年

39

在这里,您可以:

from b in _dbContext.Burden 
join bl in _dbContext.BurdenLookups on
new { Organization_Type = b.Organization_Type_ID, Cost_Type = b.Cost_Type_ID } equals
new { Organization_Type = bl.Organization_Type_ID, Cost_Type = bl.Cost_Type_ID }

这看起来更容易理解。
比贾伊·亚达夫

1

你不能那样做。在join条款(和Join()扩展方法)仅支持等值连接。这也是原因,为什么它使用equals而不是==。而且即使您可以执行类似的操作,也不会起作用,因为join它是内部联接,而不是外部联接。


不需要外部连接,并且(请参阅其他答案)显然可以。
edc65

0

这适用于2个表。我有3个表,on子句必须链接3个表中的2个条件。我的代码:

从_dbContext.p中的p开始。产品在p.ProduktId上的_dbContext.ProductVariants中加入pv等于pv.ProduktId在new {VariantId = pv.Vid,ProductId = p.ProduktId}上在leftJoinQuery中加入jpr等于新的{VariantId = jpr.Prices.VariantID, ProductId = jpr.Prices.ProduktID}转换为lj

但是它此时显示出错误:在p.ProduktId上的_dbContext.ProductVariants中加入pv等于pv.ProduktId

错误:join子句中的表达式之一的类型不正确。调用“ GroupJoin”时类型推断失败。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.