动态修改LINQ查询中的Where条件

Jon*_*ood 7 c# linq entity-framework predicate

以下实体框架查询运行时没有错误.

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();
Run Code Online (Sandbox Code Playgroud)

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

LINQ to Entities不支持LINQ表达式节点类型"Invoke".

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

Cri*_*scu 2

filterProgram将的类型更改为Expression<Func<Program, bool>>,然后它应该可以在 LINQWhere 子句中使用。

不过,有一点需要注意:我设法让它在方法链语法中工作,但在查询语法中却不行。

例如,这有效:

dataContext.Programs.Where (filterProgram)
Run Code Online (Sandbox Code Playgroud)

但这并没有:

from p in dataContext.Programs
where filterprogram 
Run Code Online (Sandbox Code Playgroud)

(编译器抱怨它无法解析 method ,该方法在和Where上都可用。)IEnumerableIQueryable

对于您的情况,更换线路可能是可以接受的

join p in repository.Query<Program>()
Run Code Online (Sandbox Code Playgroud)

join p in repository.Query<Program>().Where(filterProgram)
Run Code Online (Sandbox Code Playgroud)