使用LinqKit将查询应用于单个复杂属性

时间:2015-01-26 18:38:14

标签: c# linq entity-framework linqpad linqkit

编辑:我在LinqPad的帮助下设法将代码缩减到最小公分母。

我有一个返回复杂LinqKit谓词的方法。期望的结果是每当我需要执行此查询时都能够重用此方法。它对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)); 子句工作正常,但我不知道如何在我将这个实体作为单个实体时使用这个谓词对象的属性,并希望使用谓词来查询该实体的其他属性。

我将简要介绍一下我的意思。

StructureAnalyses.AsExpandable().Where(query).Dump();

这样可以正常工作:

StructureAnalyses

...假设IQueryable是来自实体框架的StructureAnalysisquery个对象。

但是,让我们说我想获取任务,使用相关的StructureAnalyses进行过滤。 我该怎么做?请记住,实际上,predicate是由可重用的函数构建的,而Tasks.AsExpandable().Where(predicate).Dump(); 是在一个单独的函数中构建的它,所以我不能简单地合并这两个查询。

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

Tasks

...与&#34;参数&#39; t&#39;未绑定在指定的LINQ to Entities查询表达式中。&#34; 等。在此示例中,Task是一个IQueryable,其中包含我的数据库中的所有 predicate = predicate.And(t => query.Invoke(t.StructureAnalysis)); 类型实体。

我也尝试改变这一行:

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

...为:

Expand

那也编译但失败了,&#34;无法投射类型&System; Line.Linq.Expressions.FieldExpression&#39;输入&#39; System.Linq.Expressions.LambdaExpression&#39;。&#34; ,这是可以理解的。

我还尝试在querycompiled上调用Utility,但这些都没有效果,以及以下&#34;解决方案&#34;:< / p>

1 个答案:

答案 0 :(得分: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();