【问题标题】:Passing predicate to LINQ where clause将谓词传递给 LINQ where 子句
【发布时间】:2017-08-23 07:06:16
【问题描述】:

嘿,我有以下代码:

    Func<Assoc, bool> predicate = (x) => 
    (
        !String.IsNullOrWhiteSpace(version) ? x.Version.Contains(version) : x.Version != null

    );

    var assocs = _context.Assoc
                    .Where(x => x.Model == model)
                    .Where(predicate)
                    ;

但它不起作用。如果我尝试执行此服务器会给我内部服务器异常但如果我将其更改为

var assocs = _context.Assoc
      .Where(x => x.Model == model)
      .Where(x => x.Version.Contains(version))
;

它按我的预期工作。

这是为什么呢?

是否可以预览 Linq 生成的查询?

【问题讨论】:

  • EF 无法解释您必须构建一个表达式的代码,该表达式可以翻译成 SQL。也许这对你有帮助stackoverflow.com/questions/35346630/…
  • 是否需要使用谓词?您总是可以使用 && 在 Linq 中归档相同的语句。例如,创建一个返回 bool 的方法并将其插入 && 子句。
  • 使用谓词会很棒,因为不需要版本,所以我决定像上面那样使用谓词。这很奇怪,因为在其他类似的方法中它可以正常工作
  • 请阅读@RandRandom 链接文章。您必须为所有 IQueryable&lt;T&gt; 传递表达式 (Expression&lt;Func&lt;TEntity,TResult&gt;&gt;) 而不是委托 (Func&lt;TEntity, TResult&gt;)。对于IEnumerable&lt;T&gt;,delgate 也可以工作,因为它确实在内存中评估它。但是IQueryable&lt;T&gt;需要翻译成SQL,所以必须是表达式
  • 您的错误来自语句周围的括号。使用方括号时,如果没有 return 语句,它不会自动返回。

标签: c# linq asp.net-core


【解决方案1】:

使用 LINQKit,您可以创建将为您扩展的谓词,以便您可以在 IQueryable 表达式中使用它们,但您不需要仅排除版本测试。

var assocs = _context.Assoc
             .Where(x => x.Model == model);
if (!String.IsNullOrWhiteSpace(version))
    assocs = assocs.Where(x.Version.Contains(version));

【讨论】:

    【解决方案2】:

    因为 EF 可以将 Contains 方法转换为 sql (Version LIKE '%@version%'),但不能评估您的“外部”函数。

    如果您将结果加载到 memroy(通过导出方法为 ToList()),您可以将其作为 linq2object:

    var assocs = _context.Assoc.ToList()
                    .Where(x => x.Model == model)
                    .Where(predicate);
    

    我的代码显示和说明,但绝对不推荐,因为质疑数据库比处理内存更好。

    【讨论】:

    • 为什么要提供你不推荐的答案?
    • @RandRandom 因为我认为问题是为什么
    • 你不应该至少把ToList放在第一个Where之后吗?
    • 这里的ToList 只是阻止应用第一个过滤器。第二个过滤器不是Expression,一开始就没有提供给查询提供者,因此提供者不会翻译失败(甚至不会尝试)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    相关资源
    最近更新 更多