我们使用EF进行数据访问,我们有这样的查询:
Expression<TTable, bool> expression = CreateSomeExpression();
var filter = finalExpression.Compile();
var results = db.t_Table.Where(filter).Select(x=>...);
我的问题是,EF会在给定编译表达式的情况下构造正确的查询吗?
例如,如果我的表是:
t_Table
( key int,
value_1 varchar(30),
value_2 varchar(30)
)
要编译的表达式是
p => p.value_1 = 100
这会将(在EF中)转换为:
select * from t_Table where value_1 = 100
或将转换为
select * from t_Table
然后对结果进行linq查询?
有没有办法检查EF实际上会在DB上调用哪些SQL查询?
非常感谢,
更新
虽然接受的答案100%正确(因此是接受的答案),但我的问题的解决方案是简单地删除编译。删除它会导致正确的SQL查询使用正确的where clause
。
答案 0 :(得分:6)
您编译的表达式(导致类型为Func<TTable, bool>
的代理) 实际上会导致表格满载,即
select * from t_Table
...然后在将实体加载到内存后对其进行过滤。
实体框架只能将表达式(即Expression<Func<TTable, bool>>
)转换为SQL查询。它不能反汇编已编译的委托(Func<TTable, bool>
),以便随后将其转换为SQL查询。
这是重载决策发挥作用的地方。 DbSet<T>
同时实现了IQueryable<T>
和IEnumerable<T>
。
当您在IQueryable<T>
上使用扩展方法(并且大多数接受表达式参数,即Where<T>(Expression<Func<T, bool>>)
)时,您将在数据库引擎中执行查询。
每当您切换到IEnumerable<T>
扩展方法(即Where<T>(Func<T, bool>)
)时,EF别无选择,只能将完整的实体集加载到内存中,然后在生成的缓存中迭代将与任何其他内存中的集合。