【问题标题】:Entity Framework sub query实体框架子查询
【发布时间】:2010-01-02 16:08:22
【问题描述】:

如何在 EF 中编写这样的子查询?

select * from table1 where col1 in (select col1 from table2 where col2 = 'xyz')

select * from table1 where col1 not in (select col1 from table2 where col2 = 'xyz')

我尝试过类似的方法

from t1 in table1
where (from t2 in table2 where col2 = 'xyz' select t2.col1).Contains(t1.col1)
select t1

from t1 in table1
where !(from t2 in table2 where col2 = 'xyz' select t2.col1).Contains(t1.col1)
select t1

这些查询运行良好 LinqPad 或 Linq to Sql

【问题讨论】:

  • 如果现有答案不是您想要的,请在您尝试使用您发布的那些查询表达式时发布发生了什么。你得到一个编译时错误吗?运行时错误?错误是什么?还是您根本没有得到预期的结果?
  • 首先感谢您的即时回复!这就是我想要完成的 - select * from table1 where somestringmanipulation(col1) in (select somestringmanipulation(col1) from table2 where col2 = 'xyz') where table1 和 table2 没有任何关系。尝试使用 Contains 时出现以下错误,但它在 LinqPad 中给出结果 LINQ to Entities 无法识别方法 'Boolean Contains[Int32](System.Linq.IQueryable`1[System.Int32], Int32 )' 方法,并且该方法不能翻译成 store 表达式。
  • 如果不使用 IN 或 NOT IN,我认为我无法做到这一点,暂时我计划使用存储过程,稍后我会研究 stackoverflow.com/questions/374267/…
  • 您所写的查询绝对不需要IN/NOT IN。我不怀疑实际情况比您的示例更复杂-但我建议您尝试找到一种使用简单联接的方法,因为它们更易于阅读/维护并且通常会带来更好的性能(尤其是@ 987654328@,这是一个可怕的)。或许如果你提供一个更具体的例子,有人可以帮助你。
  • 请用您正在尝试做的事情更新原始问题;我会相应地编辑我的答案。并且具体一点——一些 .NET 字符串操作可以转换为 SQL,而有些则不能。

标签: .net entity-framework subquery


【解决方案1】:

这种类型的子查询可以展平为一个连接,这是我在这里选择的写法:

SQL 版本:

SELECT t1.col1, t1.col2, t1.col3, ...
FROM table1 t1
INNER JOIN table2 t2
    ON t1.col1 = t2.col1
WHERE t2.col2 = 'xyz'

Linq 版本:

var query =
    from t1 in context.Table1
    where t1.AssociationToTable2.Col2 == "xyz"
    select new { t1.Col1, t1.Col2, ... };

AssociationToTable2 是关系属性,它会自动进行连接。或者,如果您没有关系:

var query =
    from t1 in context.Table1
    join t2 in context.Table2
        on t1.Col1 equals t2.Col1
    where t2.Col2 == "xyz"
    select new { t1.Col1, t1.Col2, ... };

您可以针对NOT IN 进行相应调整,但如果可以避免的话,我建议永远不要使用NOT IN - 性能会下降,而且几乎总是意味着设计错误。

如果您绝对必须以“IN”方式进行操作,我建议您查看this question 中的答案。

【讨论】:

    【解决方案2】:

    如果有外键,您应该只使用关联属性并让 EF 将其转换为正确的连接/子查询,例如:

    from t1 in table1
    where t1.Table2.col2 == "xyz"
    select t1
    

    不确定您的具体情况,但一个关键区别是 EF 默认不执行延迟加载,因此您可能需要 Include() 列(在使用的 linq-to-sql 或 LinqPad 中不需要这个linq-to-sql) 来预先加载它们,或者之后加载()。

    http://msdn.microsoft.com/en-us/library/bb896249.aspx

    如果你最终能分享一些更具体的架构,我希望我们可以确定这是否是正在发生的事情。

    【讨论】:

    • 延迟加载在这里不应该是一个问题,因为这是一个查询转换 - 它实际上从未在 CLR 中评估 t1.Table2.col2。如果 Linq to SQL(LinqPad 使用)之间存在差异,那么我怀疑这是因为 EF 不知道如何按照其编写方式转换表达式,但当然我们必须知道当他尝试他的时候实际发生了什么查询以便确定。
    • Aaron 是正确的:延迟加载(或不)不会在这里成为一个因素。
    猜你喜欢
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    相关资源
    最近更新 更多