我们正在使用 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 在数据库上实际调用了哪些 sql 查询?
非常感谢,
更新
虽然接受的答案是 100% 正确的(因此是接受的答案),但我的问题的解决方案是简单地删除编译。删除它会导致使用正确的 where 子句
进行正确的 SQL 查询。
最佳答案
您编译的表达式(生成一个类型为 Func<TTable, bool>
的委托(delegate))将,事实上,导致表的完全加载,即
select * from t_Table
... 然后在将实体加载到内存中后对其进行过滤。
Entity Framework 只能将表达式(即Expression<Func<TTable, bool>>
)翻译成SQL 查询。它无法反汇编已编译的委托(delegate) ( 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 别无选择,只能将完整的实体集加载到内存中,然后像处理任何其他内存中集合一样迭代生成的缓存。
关于c# - Entity Framework 和编译表达式性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34674785/