2012-06-16 17 views
6

Ich habe eine Erweiterungsmethode über IQueryable Typ erstellt, die eine Teilmenge von Entitäten und filtert sie nach einigen Kriterien. Mein Problem ist, dass ich einen Unionsausdruck der Variablen nicht zurückgeben kann, ohne dass alle zuerst initialisiert werden. Nullwerte, so wie sie sind, sind nicht gültig.Wie sollte ich IQueryable-Variablen initialisieren, bevor ein Union-Ausdruck verwendet wird?

public static IQueryable<Person> FilterHairColors(this IQueryable<Person> subQuery, string[] hairColors) 
    { 
     IQueryable<Person> q1 = null; 
     IQueryable<Person> q2 = null; 
     IQueryable<Person> q3 = null; 
     IQueryable<Person> q4 = null; 

     foreach (var value in hairColors) 
     { 
      switch (value) 
      { 
       case "1": 
        q1 = subQuery.Where(p => p.HairColor_bright == true); 
        break; 
       case "2": 
        q2 = subQuery.Where(p => p.HairColor_brown == true); 
        break; 
       case "3": 
        q3 = subQuery.Where(p => p.HairColor_dark == true); 
        break; 
       case "4": 
        q4 = subQuery.Where(p => p.HairColor_red == true); 
        break; 
      } 
     } 
     return q1.AsQueryable().Union(q2.AsQueryable()).Union(q3.AsQueryable()).Union(q4.AsQueryable()); 
    } 

Der dargestellte Codeblock Teil mehrere mehr ist, und jeder erzeugt eine Untergruppe von Daten, übertragen zu einem nachfolgenden Filterungsverfahren auf diese Weise:

results = persons.FilterGender(vm.gender).FilterAge(vm.age).FilterHeight(vm.height)...... 

Antwort

3

Sie Union nicht anrufen, wenn eine der Argumente sind null.

Was bedeutet eine "Null-Abfrage" für Sie? Wenn es "keine Zeilen" bedeutet, dann vereine es nicht. Wenn es "alle Zeilen" bedeutet, müssen Sie nicht Union, weil Sie einfach die zugrunde liegende, ungefilterte Abfrage nehmen können.

So:

var result = new [] { q1, q2, q3, q4, }.Where(query => query != null).Aggregate(Queryable.Union); 

Dies wird mithilfe von LINQ-to-Objects eine LINQ to SQL-Abfrage zu erstellen.

Eine neue Version:

var result = dataContext.Persons.Where(_ => false); 
if(q1 != null) result = result.Union(q1); 
if(q2 != null) result = result.Union(q2); 
if(q3 != null) result = result.Union(q3); 
if(q4 != null) result = result.Union(q4); 

Der SQL Server-Abfrageoptimierer wird die erste Dummy-Abfrage entfernen, so dass es überhaupt keine Laufzeit gekostet hat.

+0

Wie sollte ich Union mit Nicht-Null-Variablen durchführen? –

+0

Ich habe einen Vorschlag hinzugefügt. – usr

+0

Danke 'usr'. Kannst du dir eine einfachere, intuitivere Möglichkeit vorstellen, auf mein Problem zuzugreifen? –

1
public static IQueryable<Person> FilterHairColors(this IQueryable<Person> subQuery, string[] hairColors) 
{ 
    var result = new Person[] { }.AsQueryable(); 
    var contains = new Dictionary<string, Expression<Func<Person, bool>>>(); 

    contains.Add("1", p => p.HairColor_bright); 
    contains.Add("2", p => p.HairColor_brown); 
    contains.Add("3", p => p.HairColor_dark); 
    contains.Add("4", p => p.HairColor_red); 

    foreach (var color in hairColors) 
    { 
     result = subQuery.Where(contains[color]).Union(result); 
    } 

    return result; 
} 
+0

Ich habe das versucht, und es kam mit diesem Fehler: "Diese Methode unterstützt LINQ zu Entity-Infrastruktur und soll nicht direkt aus Ihrem Code verwendet werden". Siehe Thema Einblenden: http://social.msdn.microsoft.com/Forums/is/adodotterentityframework/thread/3962b925-fe1e-4b96-ade3-5cb3b4be4511 –