動的フィルターを作成する必要があり、エンティティを使い続けたいと思いました。このため、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に実装されています。
他の誰かがこのエラーを経験し、それを解決する方法を知っていますか?
同じエラーが発生しました。問題は、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呼び出しを必要としないので、チェックする価値があります。
私はこのエラーを受け取り、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!
}
お役に立てれば! :-)