以下 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。
你有两个选择:
- 将您的电话改为
filterProgram
使用更基本的 C# 表达式。取决于filterProgram
的复杂性这可能是不可能的。 - 删除您调用给
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/