2010-06-01 13 views
54

Potrzebowałem zbudować filtr dynamiczny i chciałem dalej używać encji. Z tego powodu chciałem użyć PredicateBuilder z albahari.C# PredicateBuilder Entities: Parametr "f" nie był powiązany w określonym wyrażeniu zapytania LINQ do Entity

stworzyłem następujący kod:

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

Kiedy wpadłem kod był tylko 1 filtr, który nie był filtr data. Tak więc wypełniono tylko wewnętrzny predykat. Po wykonaniu predykatu otrzymałem następujący błąd.

Parametr „F” nie jest ograniczone w określonym LINQ do podmiotów zapytania ekspresji.

Podczas wyszukiwania odpowiedzi znalazłem następujące page. Ale to już jest zaimplementowane w LINQKit.

Czy ktoś jeszcze doświadczył tego błędu i wiedział, jak go rozwiązać?

Odpowiedz

121

natknąłem się tego samego błędu, problem wydawał się być, gdy miałem predykaty wykonane z PredicateBuilder które były z kolei składa się z innych orzeczników wykonanych z PredicateBuilder

np (A OR B) ORAZ (X OR Y), gdzie jeden twórca tworzy A OR B, tworzy X OR Y i trzeci AND razem.

Przy tylko jednym poziomie predykatów AsExpandable działało poprawnie, gdy wprowadzono więcej niż jeden poziom, otrzymałem ten sam błąd.

Nie udało mi się znaleźć żadnej pomocy, ale dzięki próbom i błędom mogłem sprawić, że wszystko zaczęło działać. Za każdym razem, gdy wywoływałem predykat, podążałem za nim z rozszerzeniem.

Oto kawałek kodu, wycięte na prostocie:

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; 
} 

Zapytanie jest IQueryable który miał już AsExpandable nazywa, ConstructOptionNotMatchPredicate zwraca wyrażenie.

Gdy minęliśmy błąd, z pewnością udało nam się zbudować skomplikowane filtry w środowisku wykonawczym względem struktury encji.

Edit:

Ponieważ ludzie są nadal komentując i głosując się to zakładam, że jest nadal przydatna tak dzielę kolejną poprawkę. Zasadniczo przestałem używać LinqKit i jego konstruktora predykatów na rzecz tego Universal Predicate Builder, który ma ten sam interfejs API, ale nie potrzebuje wywołań Expand, co jest warte sprawdzenia.

+0

Musiałem również usunąć wywołanie AsExpandable() z mojego oryginalnego obiektu IQueryable. –

+2

Dobra odpowiedź, ale wprowadzająca w błąd. Odpowiedź BloodBaza jest prostszą, bardziej poprawną odpowiedzią – Mick

44

mam ten błąd i wyjaśnienie Mant101 ma mi odpowiedź, ale może być szukasz prostszy przykład, który powoduje problem:

// 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! 
} 

nadzieję, że to pomaga! :-)

Powiązane problemy