0

编辑:在 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();

...假设StructureAnalysesIQueryable我的一个StructureAnalysis来自 Entity Framework 的对象。

但是假设我想获取任务,使用相关的结构分析进行过滤。我怎么能做这样的事情?请记住,实际上,query它是由可重用函数predicate构建的,并且是在调用它的单独函数中构建的,因此我不能简单地合并两个查询。

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

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

...带有“参数 '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'。” 这是可以理解的。

我也尝试过调用Expandand querycompiled但没有效果,以及以下“解决方案”:

4

1 回答 1

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();
于 2015-01-27T14:08:22.597 回答