在 LINQ 语句之间共享 where 子句

发布于 2024-12-21 01:41:35 字数 1788 浏览 5 评论 0原文

我有几个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浪荡不羁 2024-12-28 01:41:35

这种构造在本机 L2S/L2Entities 提供程序中是不可能的。您必须使用 LINQKit 库,它支持表达式扩展。

Such constructions are not possible in native L2S/L2Entities provider. You must use LINQKit library, which supports expression expanding.

圈圈圆圆圈圈 2024-12-28 01:41:35

使用 CompiledQuery 创建委托。我很确定它可以在 LINQ to Entities 中工作。您只需包含 DataContext 类型作为第一个参数。

Func<MyDataContext, Table1, Table2, bool> specialCondition =
    CompiledQuery.Create(
        (MyDataContext dc, Table1 t1, Table2 t2) =>
            t1.Field1 > t2.Field3
         && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any());

然后要使用它,您应该能够执行以下操作:

var query =
    from t0 in db.Table0
    from t1 in db.Table1
    from t2 in db.Table2
    where t0.Field7 == 'something' && specialCondition(db, t1, t2)
    select t1

Create the delegate using a CompiledQuery. I'm pretty sure it works in LINQ to Entities. You just need to include the DataContext type as the first parameter.

Func<MyDataContext, Table1, Table2, bool> specialCondition =
    CompiledQuery.Create(
        (MyDataContext dc, Table1 t1, Table2 t2) =>
            t1.Field1 > t2.Field3
         && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any());

Then to use it, you should be able to do this:

var query =
    from t0 in db.Table0
    from t1 in db.Table1
    from t2 in db.Table2
    where t0.Field7 == 'something' && specialCondition(db, t1, t2)
    select t1
心是晴朗的。 2024-12-28 01:41:35

将 LINQ 查询重写为 LINQ 表达式语法,并将表达式传递到 Where(表达式)

Rewrite your LINQ query to LINQ expression syntax and pass your expression to Where(expression).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文