c# - 在 LINQ 查询中动态修改 Where 条件

标签 c# linq entity-framework predicate

以下 Entity Framework 查询运行无误。

Predicate<Program> filterProgram;
if (programId.HasValue)
    filterProgram = (p => p.Id == programId && !p.IsDeleted);
else
    filterProgram = (p => !p.IsDeleted);

var analytics = (from a in repository.Query<Analytic>()
                 where (a.Marker == "Open" || a.Marker == "LastTouch") &&
                 a.EntityType == "Proposal" &&
                 a.Site == "C"
                 join p in repository.Query<Program>()
                 on a.EntityId equals p.Id
                 //where filterProgram(p)
                 group a
                 by new { a.LoginSessionId, a.EntityId, p.Id, p.Name } into g
                 let f = g.OrderBy(x => x.TimestampUtc).FirstOrDefault(x => x.Marker == "Open")
                 where f != null
                 let t = g.FirstOrDefault(x => x.Marker == "LastTouch" && x.TimestampUtc > f.TimestampUtc)
                 select new
                 {
                     ProgramId = g.Key.Id,
                     Program = g.Key.Name,
                     ProposalId = g.Key.EntityId,
                     FirstOpen = f,
                     LastTouch = (t ?? f).TimestampUtc
                 }).ToList();

但是,如果我取消注释 where filterProgram(p) 行,我会得到运行时错误:

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.

我期望 LINQ 能够将我的谓词合并到查询中并将其转换为 SQL。为什么会出现此错误,有没有办法以这种方式动态修改 where 谓词?

最佳答案

问题是因为Entity Framework需要能够将你的LINQ查询转换成SQL。您的 LINQ 查询被编译成一个称为表达式树的数据结构,然后传递给 Entity Framework 以转换为 SQL。

你有两个选择:

  1. 将您的电话改为 filterProgram使用更基本的 C# 表达式。取决于 filterProgram 的复杂性这可能是不可能的。
  2. 删除您调用给 filterProgram 的电话, 并将此查询转换为 IEnumerable<T> , 也许通过调用 .ToList() .然后,您可以使用 filterProgram 进一步过滤此查询的结果。

例子2

   var query = /* Your Query With filterProgram commented out */
   var resultsFromSql = query.ToList();
   var fullyFiltered = resultsFromSql.Select(filterProgram);

关于c# - 在 LINQ 查询中动态修改 Where 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14598714/

相关文章:

c# - 如何正确使用 Task.WhenAll

c# - LINQ to XML - 使用前缀访问后代

c# - ASP.NET MVC5 : Want to update several items in Collection with model binding

c# - 提供 IDbContextFactory 的实现。但是哪里?

entity-framework - 使用 EF Core 记录查询持续时间

c# - 使用 AutoMapper 的 IMappingEngine 和 DI 有什么好处(如果有的话)

c# - 异步 lambda 表达式转换为 'Task' 返回委托(delegate)无法返回值

c# - C#中小时和分钟的时间跨度计算

c# - 如何在 LINQ 中查询基于链接表的数据

c# - 将数组拆分为特定长度的子数组