2009-05-30 2 views
4

ich meine eigenen Erweiterungsmethoden von IQueryable < bin mit> verkettbar Anfragen wie FindAll(). FindInZip (12345) .NameStartsWith ("XYZ") erstellen. OrderByHowIWantIt () usw., die dann bei verzögerter Ausführung eine einzige Abfrage basierend auf meiner Erweiterungsmethode-Kette erstellt.Extend IQueryable <T> Wo() oder anstelle von AND-Beziehung

Das Problem dabei ist jedoch, dass alle Wo in der Verlängerung der Kette (FindXYZ, FindInZip etc.) werden immer kombinieren und was bedeutet, ich nicht so etwas tun kann.

FindAll() FirstNameStartsWith ("X"). OrLastNameStartsWith ("Z"), weil ich nicht weiß, wie ich das OR in eine separate Where-Methode injizieren kann.

Irgendeine Idee, wie ich das lösen kann?


zusätzlich; Bis jetzt verstehe ich, wie man Ausdrücke kettet, oder wenn ich sie einschließe (zB CompileAsOr (FirstNameStartsWith ("A"). LastNameStartsWith ("Z"). OrderBy (..))

Was ich versuche zu tun obwohl es etwas komplizierter ist (und PredicateBuilder hilft hier nicht ..) in dem ich möchte, dass IQQueryable grundsätzlich auf die Where-Bedingungen zugreift, die vorher eingerichtet wurden, ohne sie zu wickeln, um das Oder zwischen ihnen zu erstellen Jede Erweiterungsmethode gibt IQueryable zurück <> Ich verstehe, dass es das Wissen über den aktuellen Status von Abfragebedingungen irgendwo haben sollte, was zu der Annahme führt, dass es einen automatisierten Weg oder ein Erstellen von Or über alle vorherigen Where-Bedingungen ohne Umbruch geben sollte was du willst Or'd.

+0

Ich fusionierte Ihre Nachfolge-Frage in diesem (und löschte das Duplikat-Konto). Ich bin mir nicht sicher, ob deine Frage (mit der zweiten Hälfte) beantwortet wird; könntest Du das erläutern? Den "aktuellen Status der Abfragebedingungen" - das ist schwer, weil die Abfrage schließlich in TSQL übersetzt wird. –

+0

Wenn du meinst, du möchtest eine Anzahl bestehender Where-Bedingungen nehmen und sie in Or umwandeln ... meinst du damit, dass/z "? Sie könnten es wahrscheinlich tun, indem Sie einen separaten LINQ-Wrapper mit einer Where-Methode erstellen, aber ich empfehle es nicht ... Wenn Sie wirklich daran interessiert sind, fügen Sie einen Kommentar zu meiner Antwort hinzu und ich werde ein Beispiel zusammenklopfen. –

+0

Hallo Marc, das ist genau was ich meine. Wenn Sie mir ein Beispiel geben können, würde das sehr geschätzt werden! Ich danke dir sehr! – Alex

Antwort

3

Ich gehe davon aus, die verschiedenen Teile der Abfrage werden nur zur Laufzeit bekannt ist, dh Sie können nicht nur || Verwendung in einem where ...

Eine faule Option ist Concat - aber dies neigt dazu, zu führen schlechte TSQL etc; Allerdings neige ich dazu, stattdessen Expression s zu schreiben. Die Vorgehensweise hängt davon ab, was der Anbieter ist, da LINQ-to-SQL verschiedene Optionen für EF (zum Beispiel) unterstützt - was hier eine echte Auswirkung hat (da Sie keine Unterausdrücke mit EF verwenden können). Kannst du uns was sagen?


Hier ist ein Code, der mit LINQ-to-SQL funktionieren sollte; Wenn Sie ein Array (oder eine Liste, und rufen Sie .ToArray()) von Ausdrücken erstellen, sollte es gut funktionieren; Beispiel hierfür ist LINQ-to-Objects, sollte aber immer noch funktionieren:

static void Main() 
    { 
     var data = (new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).AsQueryable(); 

     var predicates = new List<Expression<Func<int, bool>>>(); 
     predicates.Add(i => i % 3 == 0); 
     predicates.Add(i => i >= 8);   

     foreach (var item in data.WhereAny(predicates.ToArray())) 
     { 
      Console.WriteLine(item); 
     } 
    } 

    public static IQueryable<T> WhereAny<T>(
     this IQueryable<T> source, 
     params Expression<Func<T,bool>>[] predicates) 
    { 
     if (source == null) throw new ArgumentNullException("source"); 
     if (predicates == null) throw new ArgumentNullException("predicates"); 
     if (predicates.Length == 0) return source.Where(x => false); // no matches! 
     if (predicates.Length == 1) return source.Where(predicates[0]); // simple 

     var param = Expression.Parameter(typeof(T), "x"); 
     Expression body = Expression.Invoke(predicates[0], param); 
     for (int i = 1; i < predicates.Length; i++) 
     { 
      body = Expression.OrElse(body, Expression.Invoke(predicates[i], param)); 
     } 
     var lambda = Expression.Lambda<Func<T, bool>>(body, param); 
     return source.Where(lambda); 
    } 
0
List<string> fruits = 
     new List<string> { "apple", "passionfruit", "banana", "mango", 
       "orange", "blueberry", "grape", "strawberry" }; 

    var query = fruits.AsQueryable(); 

    // Get all strings whose length is less than 6. 
    query = query.Where(fruit => fruit.Length < 6); 

    // Hope to get others where length is more than 8. But you can't, they're gone. 
    query = query.Where(fruit => 1 == 1 || fruit.Length > 8); 

    foreach (string fruit in query) 
     Console.WriteLine(fruit); 
Verwandte Themen