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

... Entity Framework からの私のオブジェクトの 1 つでStructureAnalysesあると仮定します。IQueryableStructureAnalysis

しかし、関連する StructureAnalyses でフィルタリングして、タスクを取得したいとしましょう。どうすればそのようなことができますか?実際にqueryは、再利用可能な関数によって構築され、predicateそれを呼び出す別の関数で構築されていることに注意してください。そのため、2 つのクエリを単純にマージすることはできません。

コンパイルはできますが、クエリを実行しようとすると失敗します。

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

...with "パラメーター 't' は、指定された LINQ to Entities クエリ式にバインドされていません。" など。この例では、DB 内のすべての型エンティティ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' にキャストできません」で失敗します。当然のことです。

Expandまた、 との両方queryを呼び出してみましcompiledたが、効果はありませんでした。また、次の「解決策」も試しました。

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 に答える