如何在 LINQ to Entities 中执行 SQL“在哪里存在”?

Posted

技术标签:

【中文标题】如何在 LINQ to Entities 中执行 SQL“在哪里存在”?【英文标题】:How to do a SQL "Where Exists" in LINQ to Entities? 【发布时间】:2010-11-01 23:42:04 【问题描述】:

我真的很想做这样的事情:

Select * 
from A join B on A.key = B.key join C on B.key = C.key -- propagated keys
where exists (select null from B where A.key = B.key and B.Name = "Joe") and
      exists (select null from C where B.key = C.key and C.Name = "Kim")

使用 Entity Framework 4 和 C# 的 linq 语句会是什么样子?

更新:

显然 .Contains() 将产生“存在的地方”结果。所以,再一次尝试(我不知道这是否会编译 LOL):

var inner1 = from recordB in B
             where recordB.Name = "Joe"
             select recordB.key;

var inner2 = from recordC in C
             where recordC.Name = "Kim"
             select recordC.key;

var result = from recordA in A
             where inner1.Contains( recordA.key) &&
                   inner2.Contains( recordA.key)
             select recordA;

编辑:哇,这实际上是有效的:

var result = from A in Products
             where A.kfield1 == 1 && A.kfield2 == 2 &&
                   ( from B in Btable
                     where B.otherid == "Joe" &&  // field I want to select by
                           B.kfield1 == A.kfield1 &&     
                           B.kfield2 == A.kfield2 // Can keep adding keys here
                     select A.identifier  // unique identity field 
                   ).Contains(A.identifier) &&
                   ( from C in Ctable
                     where C.otherid == "Kim" &&  // field I want to select by
                           C.kfield1 == A.kfield1 &&     
                           C.kfield2 == A.kfield2 // Can keep adding keys here
                     select A.identifier  // unique identity field 
                   ).Contains(A.identifier)
             select A;

这产生了这个 SQL:

SELECT [t0].[identifier], [t0].*
FROM [A] AS [t0]
WHERE ([t0].[kfield1] = @p0) AND ([t0].[kfield2] = @p1) AND (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [B] AS [t1]
    WHERE ([t0].[identifier] = [t0].[identifier]) AND ([t1].[otherid] = @p2) AND
          ([t1].[kfield1] = [t0].[kfield1]) AND 
          ([t1].[kfield2] = [t0].[kfield2]))) AND (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [C] AS [t2]
    WHERE ([t0].[identifier] = [t0].[identifier]) AND ([t2].[otherid] = @p3) AND
          ([t2].[kfield1] = [t0].[kfield1]) AND 
          ([t2].[kfiekd2] = [t0].[kfield2]) ))

这正是我想要的。注意 [t0].[identifier] = [t0].[identifier],它会过滤掉 null 值,因为 null 不等于任何东西,包括它自己(在 SQL 中)

【问题讨论】:

【参考方案1】:

.Any() 扩展方法通常映射到exists

【讨论】:

这是一件非常好的事情。到目前为止,我在 Internet 上发现的唯一内容是 SO 答案之外的 .Contains() 。我见过 .Any() 使用过,但我没有把两个和两个放在一起。 这个问题最终向我展示了执行此操作的代码:***.com/questions/4084102/… growingwiththeweb.com/2013/04/…【参考方案2】:

您是否尝试将 exists 调节添加到您的联接中?

from a in context.AEntity
Join B in context.BEntity on A.Key equals B.Key && B.Name == "Joe"
Join C in context.CEntity on B.Key equals C.Key && C.Name == "Kim";

不确定这是否可行,但值得一试。

【讨论】:

不,它不会工作。 on 子句只接受 equals 表达式 再次查看您的问题,我不确定我是否理解您首先使用exists 的原因。为什么不直接添加where B.Name == "Joe" && C.Name == "Kim" 因为我正在尝试过滤具有嵌套结果的现有查询。我需要按嵌套部分过滤。我能想到的唯一方法是使用 Where exists (如果这是真的,获取记录)。 您可以使用匿名类型进行复杂的连接; join B in context.BEntity on new A.Key, B.Name equals new B.Key, "Joe" 哎呀@K0D4!这很丑陋,但可能非常有用:-)

以上是关于如何在 LINQ to Entities 中执行 SQL“在哪里存在”?的主要内容,如果未能解决你的问题,请参考以下文章

Linq to Entities 中的动态 where 子句 (OR)

在 LINQ to Entities 中重用选择表达式

如何在 LINQ to Entities Join 中使用 Convert.Int32() 方法?

LINQ to Entities 查询注意事项

LINQ to Entities 查询注意事项

LINQ to Entities 无法识别方法“布尔包含 [Int32]