web-dev-qa-db-ja.com

C#PredicateBuilderエンティティ:パラメータ 'f'は、指定されたLINQ toEntitiesクエリ式にバインドされていません

動的フィルターを作成する必要があり、エンティティを使い続けたいと思いました。このため、albahariのPredicateBuilderを使用したいと思いました。

次のコードを作成しました。

var invoerDatums = PredicateBuilder.True<OnderzoeksVragen>();
var inner = PredicateBuilder.False<OnderzoeksVragen>();

foreach (var filter in set.RapportInvoerFilter.ToList())
{
    if(filter.IsDate)
    {
        var date = DateTime.Parse(filter.Waarde);
        invoerDatums = invoerDatums.Or(o => o.Van >= date && o.Tot <= date);
    }
    else
    {
        string temp = filter.Waarde;
        inner = inner.Or(o => o.OnderzoekType == temp);
    }
}

invoerDatums = invoerDatums.And(inner);
var onderzoeksVragen = entities.OnderzoeksVragen
                               .AsExpandable()
                               .Where(invoerDatums)
                               .ToList();

コードを実行したとき、日付フィルターではないフィルターは1つしかありませんでした。したがって、内部述語のみが入力されました。述語を実行すると、次のエラーが発生しました。

パラメータ 'f'は、指定されたLINQ toEntitiesクエリ式にバインドされていませんでした。

答えを探していると、次のことがわかりました ページ 。しかし、これはすでにLINQKitに実装されています。

他の誰かがこのエラーを経験し、それを解決する方法を知っていますか?

54
Neothor

同じエラーが発生しました。問題は、PredicateBuilderで作成された述語が、PredicateBuilderで作成された他の述語で構成されていた場合に発生したようです。

例えば(A OR B)AND(X OR Y)ここで、1つのビルダーがA OR B、1つがX =を作成しますOR Yと3番目のANDでそれらを結合します。

述語のレベルが1つしかない場合、AsExpandableは正常に機能しましたが、複数のレベルが導入されたときに同じエラーが発生しました。

助けを見つけることができませんでしたが、試行錯誤を繰り返して、物事を機能させることができました。述語を呼び出すたびに、Expand拡張メソッドを使用しました。

簡単にするために、コードを少し切り詰めました。

public static IQueryable<Submission> AddOptionFilter(
    this IQueryable<Submission> query, 
    IEnumerable<IGrouping<int, int>> options)
{
    var predicate = options.Aggregate(
        PredicateBuilder.False<Submission>(),
        (accumulator, optionIds) => accumulator.Or(ConstructOptionMatchPredicate(optionIds).Expand()));
        query = query.Where(predicate.Expand());            
    return query;
}

クエリは、すでにAsExpandableが呼び出されているIQueryableであり、ConstructOptionNotMatchPredicateは式を返します。

エラーを乗り越えると、エンティティフレームワークに対して実行時に複雑なフィルターを確実に構築することができました。

編集:

人々はまだこれについてコメントし、賛成票を投じているので、私はそれがまだ有用であると思うので、私は別の修正を共有しています。基本的に私はLinqKitの使用をやめ、これを支持する述語ビルダーです niversal Predicate Builder 同じAPIを持っていますが、Expand呼び出しを必要としないので、チェックする価値があります。

122
Mant101

私はこのエラーを受け取り、Mant101の説明で答えを得ましたが、問題を引き起こすより簡単な例を探しているかもしれません。

// This predicate is the 1st predicate builder
var predicate = PredicateBuilder.True<Widget>();

// and I am adding more predicates to it (all no problem here)
predicate = predicate.And(c => c.ColumnA == 1);
predicate = predicate.And(c => c.ColumnB > 32);
predicate = predicate.And(c => c.ColumnC == 73);

// Now I want to add another "AND" predicate which actually comprises 
// of a whole list of sub-"OR" predicates
if(keywords.Length > 0)
{
    // NOTICE: Here I am starting off a brand new 2nd predicate builder....
    // (I'm not "AND"ing it to the existing one (yet))
    var subpredicate = PredicateBuilder.False<Widget>();

    foreach(string s in keywords)
    {
        string t = s;  // s is part of enumerable so need to make a copy of it
        subpredicate = subpredicate.Or(c => c.Name.Contains(t));
    }

    // This is the "gotcha" bit... ANDing the independent
    // sub-predicate to the 1st one....

    // If done like this, you will FAIL!
//  predicate = predicate.And(subpredicate); // FAIL at runtime!

    // To correct it, you must do this...
    predicate = predicate.And(subpredicate.Expand());  // OK at runtime!
}

お役に立てれば! :-)

44
Chris Walsh