Mam to zapytanie:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
Co się stanie, maxShoeSize
jeśli firma 8 w ogóle nie będzie miała pracowników?
AKTUALIZACJA:
Jak mogę zmienić zapytanie, aby uzyskać 0, a nie wyjątek?
maxShoeSize
środku?” jeśli już go wypróbowałeś.Odpowiedzi:
Zerowanie
DefaultIfEmpty
nie jest konieczne.źródło
Max()
pustej sekwencji spowoduje błąd.Wiem, że to stare pytanie i przyjęta odpowiedź działa, ale to pytanie odpowiadało na moje pytanie, czy taki pusty zestaw skutkowałby wyjątkiem, czy
default(int)
wynikiem.Przyjęta odpowiedź jednak, choć działa, nie jest idealnym rozwiązaniem IMHO, którego nie podano tutaj. W ten sposób udzielam go w mojej własnej odpowiedzi dla dobra każdego, kto tego szuka.
Oryginalny kod OP był następujący:
Oto jak napisałbym to, aby zapobiec wyjątkom i podać domyślny wynik:
Powoduje to, że zwracany typ
Max
funkcji jestint?
, który pozwala nanull
wynik, a następnie??
zastępujenull
wynik przez0
.EDYTUJ
Aby wyjaśnić coś z komentarzy, Entity Framework obecnie nie obsługuje
as
słowa kluczowego, więc sposób zapisania go podczas pracy z EF byłby następujący:Ponieważ
[TypeOfWorkers]
może to być długa nazwa klasy i jest żmudna w pisaniu, dodałem metodę rozszerzenia, aby pomóc.To tylko uchwyty
int
, ale to samo można zrobić dlalong
,double
lub innego rodzaju wartości, czego potrzebujesz. Korzystanie z tej metody rozszerzenia jest bardzo proste, po prostu przekazujesz swoją funkcję selektora i opcjonalnie dołączasz wartość, która ma być użyta dla null, która domyślnie wynosi 0. Więc powyższe można przepisać w następujący sposób:Miejmy nadzieję, że pomoże to ludziom jeszcze bardziej.
źródło
DefaultIfEmpty
odpowiedź działa dobrze tylko wtedy, gdyMax
nie przeprowadza oceny.Select
jako pośrednika, kiedy mam zamiar używać funkcji agregującej, takiej jakMax
na wyniku. Ja również myślę (nie testowałem tego jeszcze), że wygenerowany SQL użyłby dodatkowy zapytanie podselekcji wykonując że chociaż będzie kopalnia właśnie do czynienia z pustym zestawem wracając null. Dzięki za uznanie i opinie! ;)ShoeSize
faktycznie w powiązanegoUniform
podmiotu, nie będę używaćWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, zamiast tego po prostu zachować całą ocenę wMax
funkcji:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Wolę używać jak najmniejszej liczby metod w moich zapytaniach, aby umożliwić EF mieć największą swobodę w decydowaniu, jak efektywnie konstruować zapytania. ;-)public static TResult MaxOrDefault<TElement, TResult>(this IQueryable<TElement> items, Expression<Func<TElement, TResult>> selector, TResult defaultValue = default) where TResult : struct => items.Select(selector).Max(item => (TResult?)item) ?? defaultValue;
Max () w takim przypadku nic nie zwróci.
Podniesie InvalidOperationException, ponieważ źródło nie zawiera żadnych elementów.
źródło
InvalidOperationException
wtedy, gdy obiekty na liście nie mają wartości null: docs.microsoft.com/en-us/dotnet/api/…źródło
Jeśli jest to Linq to SQL, nie lubię go używać,
Any()
ponieważ powoduje to wiele zapytań do serwera SQL.Jeśli
ShoeSize
nie jest polem dopuszczającym wartość null, wówczas użycie samego polecenia.Max(..) ?? 0
nie zadziała, ale następujące działania:Absolutnie nie zmienia wyemitowanego kodu SQL, ale zwraca 0, jeśli sekwencja jest pusta, ponieważ zmienia znak na
Max()
zwracającyint?
zamiastint
.źródło
(zakładając, że
ShoeSize
jest to typoweint
)Jeśli
Workers
jestDbSet
lubObjectSet
z Entity Framework, Twoje początkowe zapytanie wyrzuciłobyInvalidOperationException
, ale nie narzekało na pustą sekwencję, ale narzekało, że zmaterializowanej wartości NULL nie można przekonwertować na plikint
.źródło
Max wyrzuci System.InvalidOperationException "Sekwencja nie zawiera żadnych elementów"
źródło
Uwaga: zapytanie z
DefaultIfEmpty()
może być znacznie wolniejsze . W moim przypadku było to proste zapytanie z.DefaultIfEmpty(DateTime.Now.Date)
.Byłem zbyt leniwy, aby go profilować, ale oczywiście EF próbował uzyskać wszystkie wiersze, a następnie przyjąć
Max()
wartość.Wniosek: czasami obsługa
InvalidOperationException
może być lepszym wyborem.źródło
Możesz użyć trójargumentu wewnątrz
.Max()
do obsługi predykatu i ustawiania jego wartości;Jeśli jest taka możliwość, musisz obsłużyć
Workers
zbiór jako pusty / pusty, ale będzie to zależeć od Twojej implementacji.źródło
Możesz spróbować tego:
źródło
Możesz sprawdzić, czy są jacyś pracownicy, zanim wykonasz Max ().
źródło