在 LINQ 语句之间共享 where 子句
我有几个 LINQ-to-Entities 查询,它们命中相同的两个表并具有相同的几个条件。我想做的是在多个查询之间共享 where 子句。例如,假设我有这样的内容:
from t0 in db.Table0
from t1 in db.Table1
from t2 in db.Table2
where t0.Field7 == 'something'
&& t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any()
select t0
我希望能够这样说:
Func<Table1, Table2, bool> specialCondition
= (t1, t2) => t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any();
from t0 in db.Table0
from t1 in db.Table1
from t2 in db.Table2
where t0.Field7 == 'something' && specialCondition(t1, t2)
select t1
这会生成 The LINQ expression node type 'Invoke' is not support in LINQ to Entities.
这使得感觉。它无法将任意 .NET 函数/委托代码解析为可以传递到数据库的内容。
然而,我在互联网上读到的所有内容都说表达式树可以正常工作。我的问题是,虽然我可以声明它(它的语法与函数几乎相同),但我不知道如何使用它。
Expression<Func<Table1, Table2, bool>> specialCondition
= (t1, t2) => t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any();
我该怎么办?如何将其传递给 LINQ2EF?
更新:按照 @Mic 的推荐使用 LinqKit 的工作解决方案,从 NuGet 中提取(注意 .AsExpandable()
和 .Invoke
以及截图导入的 LinqKit 引用和命名空间):
Expression<Func<Table1, Table2, bool>> specialCondition
= (t1, t2) => t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any();
from t0 in db.Table0.AsExpandable()
from t1 in db.Table1
from t2 in db.Table2
where t0.Field7 == 'something' && specialCondition.Invoke(t1, t2)
select t1
在 LinqPad 中检查,第一个完全内联版本和最终的 LinqKit Expression 版本都生成相同的 SQL 和结果。非常感谢大家的建议和帮助。
I have several LINQ-to-Entities queries that hit the same two tables and have the same few conditions. What I'm trying to do is share the where clause between multiple queries. For example, say I have this:
from t0 in db.Table0
from t1 in db.Table1
from t2 in db.Table2
where t0.Field7 == 'something'
&& t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any()
select t0
What I would like is to be able to say something like this:
Func<Table1, Table2, bool> specialCondition
= (t1, t2) => t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any();
from t0 in db.Table0
from t1 in db.Table1
from t2 in db.Table2
where t0.Field7 == 'something' && specialCondition(t1, t2)
select t1
This generates the The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
which makes sense. It can't parse the arbitrary .NET function/delegate code into something it can pass to the database.
Everything I've read on the internet says expression trees, however, can work just fine. My problem is while I can declare it (it's pretty much the same syntax as the function), I don't know how to use it.
Expression<Func<Table1, Table2, bool>> specialCondition
= (t1, t2) => t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any();
What do I do with this? How do I pass it to LINQ2EF?
Update: Working solution with LinqKit as recommended by @Mic, pulled from NuGet (note the .AsExpandable()
and the .Invoke
and the snipped imported LinqKit reference and namespace):
Expression<Func<Table1, Table2, bool>> specialCondition
= (t1, t2) => t1.Field1 > t2.Field3
&& t2.NavigationProperty(t => t.Field4 == t1.Field2).Any();
from t0 in db.Table0.AsExpandable()
from t1 in db.Table1
from t2 in db.Table2
where t0.Field7 == 'something' && specialCondition.Invoke(t1, t2)
select t1
Checking in LinqPad, both the first completely inlined version and the final LinqKit Expression version generate the same SQL and results. Thanks a lot to you all for your suggestions and help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这种构造在本机 L2S/L2Entities 提供程序中是不可能的。您必须使用 LINQKit 库,它支持表达式扩展。
Such constructions are not possible in native L2S/L2Entities provider. You must use LINQKit library, which supports expression expanding.
使用
CompiledQuery
创建委托。我很确定它可以在 LINQ to Entities 中工作。您只需包含DataContext
类型作为第一个参数。然后要使用它,您应该能够执行以下操作:
Create the delegate using a
CompiledQuery
. I'm pretty sure it works in LINQ to Entities. You just need to include theDataContext
type as the first parameter.Then to use it, you should be able to do this:
将 LINQ 查询重写为 LINQ 表达式语法,并将表达式传递到
Where(表达式)
。Rewrite your LINQ query to LINQ expression syntax and pass your expression to
Where(expression)
.