Mam zapytanie LINQ, które wygląda następująco:
DateTime today = DateTime.UtcNow;
var results = from order in context.Orders
where ((order.OrderDate <= today) && (today <= order.OrderDate))
select order;
Próbuję się nauczyć / zrozumieć LINQ. W niektórych przypadkach muszę dodać dwie dodatkowe klauzule WHERE. Aby to zrobić, używam:
if (useAdditionalClauses)
{
results = results.Where(o => o.OrderStatus == OrderStatus.Open) // Now I'm stuck.
}
Jak widać, wiem, jak dodać dodatkową klauzulę WHERE. Ale jak dodać wiele? Na przykład chciałbym dodać
WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID
do mojego poprzedniego zapytania. Jak to zrobić za pomocą metod rozszerzających?
Dziękuję Ci!
Możesz nadal łączyć je w łańcuch, tak jak zrobiłeś.
To reprezentuje AND.
źródło
Jeśli pracujesz z danymi w pamięci (czytaj „kolekcje POCO”), możesz również łączyć swoje wyrażenia razem za pomocą PredicateBuilder w następujący sposób:
// initial "false" condition just to start "OR" clause with var predicate = PredicateBuilder.False<YourDataClass>(); if (condition1) { predicate = predicate.Or(d => d.SomeStringProperty == "Tom"); } if (condition2) { predicate = predicate.Or(d => d.SomeStringProperty == "Alex"); } if (condition3) { predicate = predicate.And(d => d.SomeIntProperty >= 4); } return originalCollection.Where<YourDataClass>(predicate.Compile());
Pełne źródło wspomnianych źródeł
PredicateBuilder
znajduje się poniżej (ale możesz też sprawdzić oryginalną stronę z kilkoma innymi przykładami):using System; using System.Linq; using System.Linq.Expressions; using System.Collections.Generic; public static class PredicateBuilder { public static Expression<Func<T, bool>> True<T> () { return f => true; } public static Expression<Func<T, bool>> False<T> () { return f => false; } public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ()); return Expression.Lambda<Func<T, bool>> (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters); } public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ()); return Expression.Lambda<Func<T, bool>> (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters); } }
Uwaga : przetestowałem to podejście z projektem Portable Class Library i muszę go użyć,
.Compile()
aby działało:źródło
Pewno:
if (useAdditionalClauses) { results = results.Where(o => o.OrderStatus == OrderStatus.Open && o.CustomerID == customerID) }
Lub po prostu inne
.Where()
wywołanie, takie jak to (chociaż nie wiem, dlaczego miałbyś chcieć, chyba że jest podzielone przez inną boolowską zmienną kontrolną):if (useAdditionalClauses) { results = results.Where(o => o.OrderStatus == OrderStatus.Open). Where(o => o.CustomerID == customerID); }
Lub ponowne przypisanie do
results
: `wyniki = wyniki. Gdzie ( bla ).źródło
możesz użyć && i zapisać wszystkie warunki w tej samej klauzuli where lub możesz .Where (). Where (). Where () ... i tak dalej.
źródło
Wybór jest zbędny, ponieważ już pracujesz nad zamówieniem.
źródło
Po prostu użyj
&&
operatora tak, jak w przypadku każdego innego stwierdzenia, które wymaga logiki boolowskiej.if (useAdditionalClauses) { results = results.Where( o => o.OrderStatus == OrderStatus.Open && o.CustomerID == customerID) }
źródło