如何在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
答案 0 :(得分:6)
这种类型的子查询可以展平为连接,这是我选择在这里写的方式:
SELECT t1.col1, t1.col2, t1.col3, ...
FROM table1 t1
INNER JOIN table2 t2
ON t1.col1 = t2.col1
WHERE t2.col2 = 'xyz'
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中查看答案。
答案 1 :(得分:0)
如果有外键,您应该只使用关联属性,让EF将其转换为正确的连接/子查询,例如:
from t1 in table1
where t1.Table2.col2 == "xyz"
select t1
不确定您的具体方案,但一个关键区别是EF默认不进行延迟加载,因此您可能需要Include()列(在linq-to-sql或LinqPad中使用它不需要linq-to-sql)急切加载它们,或者之后加载Load()。
http://msdn.microsoft.com/en-us/library/bb896249.aspx
如果你最终可以分享一些更具体的架构,我们可以确定这是不是正在发生的事情,我希望。