【问题标题】:Using Expression Class With LINQ Queries将表达式类与 LINQ 查询一起使用
【发布时间】:2016-03-31 22:31:55
【问题描述】:

我想知道是否有一种方法可以使用 Expression 类进行自定义查询,例如这样的 LINQ 查询

Expression<Func<TEntity, bool>> expression = (x) => x.Id = 1

var items = from item in context.TEntity
where expression
select item

我知道有一种方法可以使用 LINQ 函数来执行此操作,因为 Where 函数将表达式作为参数,但我确实需要使用 LINQ 查询来执行此操作

注意:上面的代码只是一个示例,让您了解我正在尝试做的事情,它不是实际的工作代码

注意 2:我需要它来使用实体框架

【问题讨论】:

    标签: c# entity-framework linq


    【解决方案1】:

    不幸的是,Entity Framework 本身并不支持这种类型的表达式投影,这就是为什么像where expression.Compile().Invoke(item); 这样的常见尝试会在运行时抛出异常的原因。

    但是,如果您使用 LinqKit 库(它利用表达式访问者)并在实体集上调用 .AsExpandable(),则可以动态调用您的表达式:

    Expression<Func<TEntity, bool>> expression = x => x.Id == 1;
    
    var items = from item in context.Set<TEntity>.AsExpandable()
    where expression.Invoke(item)
    select item;
    

    【讨论】:

    • 哎呀你是对的。 Invoke 是 Linqkit 的一个扩展方法,它与 AsExpandable 结合使用。
    • @DavidL,啊,现在说得通了。感谢您的更新。
    • @KirillShlenskiy 没问题,感谢您提出!
    【解决方案2】:

    至少在 EF Core 上有效(我刚刚测试过)。手头没有任何我可以测试的 EF6 项目。

    Expression<Func<TEntity, bool>> expression = (x) => x.Id = 1
    
    var items = from item in context.TEntity
    where expression.Compile()(item);
    select item
    

    更新:我刚刚在 EF6 上做了一个简单的测试项目,但它在那里不起作用,因为它无法识别表达式调用

    【讨论】:

    • 我真的很惊讶它在 EF Core 上工作...我必须检查它是否在进行本地过滤(我听说计划支持)或实际转换为 SQL,但我没有现在是时候了。
    • 它确实进行了本地过滤。所以他们消除了运行时异常,但是如果你想确保它在数据库端执行,你必须打开日志记录并检查每个查询。
    • @IvanStoev 是的,那是我的猜测......我尝试启用日志记录,但似乎没有一致的方法来做到这一点,我没有太多时间来测试它(他们在 3 个不同的版本中更改了 3 次,我在 github 问题上找到的最后一个方法不适用于已发布的 nuget 包)
    • @Jcl 非常有趣……可惜它不支持正确的投影。但是,看起来他们已经为 RowNumber 开始了 ExpressionVisitor 模式。也许他们会将其扩展为多种常用表达方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多