2012-06-16 6 views
6

Utworzono metodę rozszerzenia na typ IQueryable, który pobiera podzbiór encji i filtruje je według pewnych kryteriów. Mój problem polega na tym, że nie mogę zwrócić wyrażenia Unii ze zmiennych, bez uprzedniego zainicjowania wszystkiego. Wartości null, jako zaległości, są niepoprawne.Jak powinienem zainicjować zmienne IQueryable, zanim użyję wyrażenia Unii?

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

Przedstawiony blok kodu jest częścią kilka więcej, a każdy tworzy podzbiór danych, przenoszenia do kolejnego sposobu filtrowania w ten sposób:

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

Odpowiedz

3

nie nazywają Unię gdy jeden z Argumenty są puste.

Co oznacza dla Ciebie "zapytanie zerowe"? Jeśli oznacza to "bez wierszy", po prostu nie mieszaj tego. Jeśli oznacza to "wszystkie wiersze", nie ma potrzeby łączenia, ponieważ można po prostu wziąć podstawowe, niefiltrowane zapytanie.

jak poniżej:

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

to LINQ do obiektów do konstruowania zapytania LINQ-SQL.

Nowa wersja:

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

SQL Server optymalizator kwerendy usunie pierwszego zapytania manekina tak, że nie ma w ogóle koszt wykonania.

+0

W takim razie, w jaki sposób kondycjonować Unię, wykonując ją przy zmiennych niezerowych? –

+0

Dodałem propozycję. – usr

+0

Dzięki "usr". Czy możesz wymyślić prostszy, intuicyjny sposób na uzyskanie dostępu do mojego problemu? –

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

Próbowałem tego, i to wystąpił z tym błędem: "Ta metoda obsługuje infrastrukturę LINQ do Entity i nie jest przeznaczona do użycia bezpośrednio z twojego kodu". zobacz temat regading: http://social.msdn.microsoft.com/Forums/is/adodotnetentityframework/thread/3962b925-fe1e-4b96-ade3-5cb3b4be4511 –