2015-01-26 48 views
0

编辑:我设法减少我的代码在LinqPad的协助下最小公分母。使用LinqKit将查询应用到一个复杂属性

我有一个方法返回一个复杂的LinqKit谓词。期望的结果是能够在我需要执行此查询时重用此方法。它可以在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是我从实体框架StructureAnalysis对象的IQueryable

但是,让我们说我想获取任务,使用相关的StructureAnalyses进行筛选。 我该怎么做这样的事情?请记住,实际上,query是由可重复使用的函数构建而成的,而predicate是在调用它的单独函数中构建的,所以我不能简单地合并这两个查询。

它编译,但是当我尝试和执行查询失败:

Tasks.AsExpandable().Where(predicate).Dump(); 

...“参数‘T’在指定的LINQ到实体没有义务查询表达式。”等。在这个例子中,Tasks是一个IQueryable,它包含我DB中的所有Task类型实体。

我也试着改变这一行:

 predicate = predicate.And(t => query.Invoke(t.StructureAnalysis)); 

...到:

 compiled = query.Compile(); 
     predicate = predicate.And(t => compiled(t.StructureAnalysis)); 

这也编译,但失败,“无法投类型的对象“系统。 Linq.Expressions.FieldExpression'键入'System.Linq.Expressions.LambdaExpression'。“,可以理解。

我也试过在两个querycompiled,这都没有效果,以及下面的“解决方案”,呼吁Expand

+1

我认为提出的关闭原因是无效的。 – Shoe 2015-01-26 19:29:56

+0

@Shoe代码提供的不会重现问题;紧密的原因完全有效。或者你是否能够使用提供的代码重现所描述的问题? – Servy 2015-01-26 21:37:23

+0

@Servy前段时间更新了问题,并在评论中回复了您的答案。我很确定你现在可以重现它,但是如果你不能,请告诉我。 – Grinn 2015-01-26 21:44:27

回答

0

我最终发现了我自己的解决方案。诀窍是将query的调用包装在访问该属性的另一个谓词中,然后在调用该谓词时展开该谓词。因此,对于我试图在单个StructureAnalysis上调用查询的示例,我的代码现在看起来像这样:

// 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();