C# 使用LinqKit将查询应用于单个复杂属性
编辑:在LinqPad的帮助下,我成功地将代码缩减到最小公分母 我有一个返回复杂LinqKit谓词的方法。期望的结果是,无论何时需要执行此查询,都能够重用此方法。它在C# 使用LinqKit将查询应用于单个复杂属性,c#,linq,entity-framework,linqpad,linqkit,C#,Linq,Entity Framework,Linqpad,Linqkit,编辑:在LinqPad的帮助下,我成功地将代码缩减到最小公分母 我有一个返回复杂LinqKit谓词的方法。期望的结果是,无论何时需要执行此查询,都能够重用此方法。它在Where子句中针对这些实体的IQueryable集合工作得很好,但我一辈子都不知道当我将此实体作为对象的单个属性,并且希望使用谓词查询该实体的其他属性时,如何使用此谓词 我会给你一个简单的例子来说明我的意思 // Note: .Includes removed for brevity's sake. var task = Task
Where
子句中针对这些实体的IQueryable
集合工作得很好,但我一辈子都不知道当我将此实体作为对象的单个属性,并且希望使用谓词查询该实体的其他属性时,如何使用此谓词
我会给你一个简单的例子来说明我的意思
// 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));
…假设structuresanalysis
是实体框架中我的structuresanalysis
对象的IQueryable
但假设我想获得任务,使用相关的结构分析进行过滤我如何做这样的事情?请记住,实际上,查询
是由一个可重用函数构建的,而谓词
是由一个单独的调用它的函数构建的,因此我不能简单地合并这两个查询
它可以编译,但在我尝试执行查询时失败:
Tasks.AsExpandable().Where(predicate).Dump();
…使用“参数“t”未绑定在指定的LINQ to Entities查询表达式中。”,或诸如此类。在本例中,Tasks
是一个IQueryable,它包含MyDB中的所有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
,但都没有效果,还尝试了以下“解决方案”:
- 此选项似乎不完整(
未定义):实用程序
- 这句话只是简单地说,“这是做不到的”,我拒绝相信:
query
的调用封装在另一个访问该属性的谓词中,然后在调用该谓词时展开该谓词。因此,在我的示例中,我试图在单个结构分析上调用查询,我的代码如下所示:
// 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
);
//// HERE'S WHAT'S NEW ////
Expression<Func<Task, bool>> subPredicate = t => query.Invoke(t.StructureAnalysis);
predicate = predicate.And(subPredicate.Expand());
Tasks.AsExpandable().Where(predicate).Dump();
//注意:。为了简洁起见,删除了包含。
var task=Tasks.First(t=>t.qaconficttaskid==2);
var predicate=PredicateBuilder.True();
//确保任务自身的属性匹配。
谓词=谓词。和(t=>t.TaskType==task.TaskType&&
t、 Description==任务。Description&&
t、 预处理==任务。预处理&&
t、 治疗==任务治疗);
var structuresanalysis=task.structuresanalysis;
var query=PredicateBuilder.True();
查询=查询和(分析=>
//名字匹配
analysis.Name==structurealysis.Name&&
//我们有相同的进球数,所以他们都必须配合。
analysis.Goals.Count==structurealysis.Goals.Count
);
////这是最新消息////
表达式subPredicate=t=>query.Invoke(t.structuresanalysis);
谓词=谓词和(subPredicate.Expand());
Tasks.AsExpandable().Where(谓词).Dump();
我认为提议的关闭原因无效。@代码提供的原因不会重现问题;接近的理由是完全正确的。或者,您是否能够使用提供的代码重现所描述的问题?@Servy我不久前更新了Q,并在您的答案的注释中ping了您。我很确定您现在可以复制它,但如果不能,请告诉我。@Grinn当前显示的代码没有复制问题。@Servy显示的代码是在LINQPad中执行的完整代码。不过不用担心,因为我已经找到了解决当前问题的方法。
// 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
);
//// HERE'S WHAT'S NEW ////
Expression<Func<Task, bool>> subPredicate = t => query.Invoke(t.StructureAnalysis);
predicate = predicate.And(subPredicate.Expand());
Tasks.AsExpandable().Where(predicate).Dump();