【发布时间】:2015-01-27 22:14:15
【问题描述】:
编辑:在 LinqPad 的帮助下,我设法将我的代码减少到最小公分母。
我有一个返回复杂 LinqKit 谓词的方法。期望的结果是能够在我需要执行此查询时重用此方法。它在针对这些实体的IQueryable 集合的Where 子句中运行良好,但是当我将此实体作为对象的单个属性时,我终生无法弄清楚如何使用此谓词,并且想要使用谓词来查询该实体的其他属性。
我会给你一个简单的例子来说明我的意思。
// Note: .Includes removed for brevity's sake.
var task = Tasks.First(t => t.QaConfigTaskId == 2);
var predicate = PredicateBuilder.True<Task>();
// Ensure that the task's own properties match.
predicate = predicate.And(t => t.TaskType == task.TaskType &&
t.Description == task.Description &&
t.PreTreatment == task.PreTreatment &&
t.Treatment == task.Treatment);
var structureAnalysis = task.StructureAnalysis;
var query = PredicateBuilder.True<StructureAnalysis>();
query = query.And(analysis =>
// The names match
analysis.Name == structureAnalysis.Name &&
// We have the same # of goals so they must all match.
analysis.Goals.Count == structureAnalysis.Goals.Count
);
predicate = predicate.And(t => query.Invoke(t.StructureAnalysis));
这样可以正常工作:
StructureAnalyses.AsExpandable().Where(query).Dump();
...假设 StructureAnalyses 是来自 Entity Framework 的 StructureAnalysis 对象的 IQueryable。
但是假设我想获取任务,使用相关的结构分析进行过滤。 我该怎么做? 请记住,实际上,query 是由可重用函数构建的,predicate 是在调用它的单独函数中构建的,所以我不能简单地合并两个查询。
当我尝试执行查询时它编译但失败:
Tasks.AsExpandable().Where(predicate).Dump();
...with “参数 't' 未绑定在指定的 LINQ to Entities 查询表达式中。” 等。在此示例中,Tasks 是一个 IQueryable,它包含我的数据库中的所有 Task 类型实体。
我也尝试过修改这一行:
predicate = predicate.And(t => query.Invoke(t.StructureAnalysis));
...到:
compiled = query.Compile();
predicate = predicate.And(t => compiled(t.StructureAnalysis));
这也可以编译但失败,“无法将 'System.Linq.Expressions.FieldExpression' 类型的对象转换为 'System.Linq.Expressions.LambdaExpression' 类型。” 这是可以理解的。
我还尝试在query 和compiled 上调用Expand,但没有效果,以及以下“解决方案”:
【问题讨论】:
-
我认为建议的关闭原因无效。
-
@Shoe 提供的代码没有重现问题;关闭的原因是完全有效的。或者您是否能够使用提供的代码重现所描述的问题?
-
@Servy 我不久前更新了 Q 并在 cmets 中向您发送了您的答案。我很确定你现在可以重现它,但如果不能,请告诉我。
-
@Grinn 当前显示的代码没有重现问题。
-
@Servy 显示的代码是在 LINQPad 中执行的完整代码。不过不用担心,因为我已经找到了解决手头问题的方法。
标签: c# linq entity-framework linqpad linqkit