2010-03-13 4 views
7

Właśnie czytałem ostatnie pytanie na temat using conditionals in Linq i przypominało mi problem, którego nie udało mi się rozwiązać. Podczas budowania Linq do zapytań SQL programowo, jak można to zrobić, gdy liczba warunków nie jest znana do czasu wykonania?Używanie warunków w Linq Programowo

Na przykład w poniższym kodzie pierwsza klauzula tworzy IQueryable, która, jeśli wykonana, wybrałaby wszystkie zadania (zwane problemami) w bazie danych, druga klauzula doprecyzuje to do kwestii przypisanych do jednego działu, jeśli został wybrany w combobox (który ma wybraną pozycję związaną z właściwością departmentToShow).

Jak mogę to zrobić, korzystając z kolekcji selectedItems?

IQueryable<Issue> issuesQuery; 

// Will select all tasks 
issuesQuery = from i in db.Issues 
       orderby i.IssDueDate, i.IssUrgency 
       select i; 

// Filters out all other Departments if one is selected 
    if (departmentToShow != "All") 
    { 
     issuesQuery = from i in issuesQuery 
         where i.IssDepartment == departmentToShow 
         select i; 
    } 

Nawiasem mówiąc, powyższy kod jest uproszczona, w rzeczywistym kodzie istnieje około tuzina klauzul udoskonalenia kwerendę opartą na użytkowników wyszukiwania i ustawienia filtra.

Odpowiedz

7

Jeżeli liczba warunkach jest nieznany wtedy łatwiej jest używać lambda składni zamiast zrozumienia zapytania, tj:

IQueryable<Issue> issues = db.Issues; 
if (departmentToShow != "All") 
{ 
    issues = issues.Where(i => i.IssDepartment == departmentToShow); 
} 
issues = issues.OrderBy(i => i.IssDueDate).ThenBy(i => i.IssUrgency); 

(Zakładając, że chcesz zamawianie wydarzy po filtrowaniu, które powinny być przypadek - Nie jestem pewien, czy Linq wygeneruje zoptymalizowane zapytanie, jeśli najpierw spróbujesz zrobić zamówienie).

Jeśli masz bardzo dużą liczbę opcjonalnych warunków następnie można go oczyścić z predykatów:

List<Predicate<Issue>> conditions = new List<Predicate<Issue>>(); 
if (departmentToShow != "All") 
    conditions.Add(i => i.IssDepartment == departmentToShow); 
if (someOtherThing) 
    conditions.Add(anotherPredicate); 
// etc. snip adding conditions 

var issues = from i in issues 
      where conditions.All(c => c(i)) 
      orderby i.IssDueDate, i.IssUrgency; 

Albo po prostu użyć PredicateBuilder który jest prawdopodobnie łatwiejsze.

+0

Właściwie jeden element na mojej liście zadań polega na wyciągnięciu jawnego polecenia i dodaniu go do interfejsu, aby użytkownik miał jakąś kontrolę. –

+0

W powyższym wyrażeniu Lambda, jak by to działało z departmentToShow będącym kolekcją z combobox, myślałem, że to, co masz, jest dokładnie takie samo jak moje zapytanie. Muszę wyznać, że jestem początkującym, a Lambda to jedna z tych rzeczy, które mają dla mnie więcej sensu w książkach niż w praktyce. –

+0

@Mike B: Jest podobny do tego, co masz, ale oczywiście mniej gadatliwy, a twoja pierwotna wersja zamawia przed drugim filtrem (chcesz, żeby to się stało na końcu). Jeśli 'departmentToShow' jest kolekcją, to piszesz' departmentToShow.Contains (i.IssDepartment) 'zamiast' i.IssDepartment == departmentToShow'. – Aaronaught