2010-03-23 14 views
14

Poniższy kod działa, chyba że p.School.SchoolName okazuje się mieć wartość null, w takim przypadku powoduje to wyjątek NullReferenceException.linq gdzie klauzula i count powodują zerowy wyjątek

if (ExistingUsers.Where(p => p.StudentID == item.StaffID && 
         p.School.SchoolName == item.SchoolID).Count() > 0) 
{ 
    // Do stuff. 
} 

ExistingUsers jest lista użytkowników:

public List<User> ExistingUsers; 

Oto odnośny fragment stacktrace:

System.NullReferenceException: Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu .

na System.Linq.Enumerable.WhereListIterator 1.MoveNext()
at System.Linq.Enumerable.Count[TSource](IEnumerable
1 źródło)

Jak należy sobie radzić w tej klauzuli WHERE?

Dziękuję bardzo z góry.

+5

Czy jesteś pewien, że nazwa szkoły ma wartość zerową, a nie p.School? –

+6

Jako ogólna uwaga, zamiast robić IEnumerable.Count (predicate)> 0, użyj IEnumerable.Any (predicate). Spowoduje to zakończenie wykonywania pierwszego znalezionego dopasowania, co może doprowadzić do znacznego przyspieszenia. – recursive

+0

@Anthonia: wielkie dzięki, myślę, że masz rację, ponieważ p.School jest zerowy. – IntrepidDude

Odpowiedz

24

Podejrzewam, że p.School ma wartość null, a nie SchoolName. Po prostu dodaj zerową kontrolę przed uzyskaniem dostępu do SchoolName. Ponadto, użyj Any(), aby sprawdzić, czy są jakieś wyniki zamiast Count() > 0, chyba że naprawdę potrzebujesz tej liczby. Działa to lepiej, ponieważ nie wszystkie elementy są iterowane, jeśli takie istnieją.

var result = ExistingUsers.Where(p => p.StudentID == item.StaffID 
          && p.School != null 
          && p.School.SchoolName == item.SchoolID) 
         .Any(); 

if (result) { /* do something */ } 
+0

To działało jak czar. Wielkie dzięki, nauczyłem się! – IntrepidDude

0

W przypadku, gdy chcesz uzyskać wartość zerową (wszyscy uczniowie, ze szkołą lub nie) Użyj lewy dołączyć.

Są dobrym przykładem na MSDN

0

Jeśli dobrze pamiętam (nie na moim komputerze deweloperskim w tej chwili i nie można sprawdzić z reflektorem), używając == wyniki operatora w wywołaniu instance implementationstring.Equals(string), a nie wykonanie statyczne String.Equals(string, string).

Zakładając, że problem jest spowodowany SchoolName jest null, jak sugerujesz, spróbuj tego:

if (ExistingUsers.Where(
    p => p.StudentID == item.StaffID 
    && String.Equals(p.School.SchoolName, item.SchoolID)).Count() > 0) 
{ 
    // Do stuff. 
} 

Oczywiście komentarzy innych odpowiedzi liczyć także:

  • Korzystanie Any() zamiast Count() > 0 generalnie działa lepiej
  • Jeśli p.School ma wartość pustą, potrzebny będzie dodatkowy sprawdzian

Mam nadzieję, że to pomoże.

1

Dla wszystkich kolumn z zerową zerową bazą danych należy albo dodać wartość zerową, albo wykonać proste porównanie a == b zamiast a.ToLower() == b.ToLower() lub podobnych operacji na ciągach.
Moja obserwacja poniżej:
Gdy są one iterowane przez Enumerable of LINQ Query dla porównania z ciągiem wejściowym/wartością, każda wartość pusta (z kolumny bazy danych) i operacje na nim powodowałyby wyjątek, ale zmienna stała się NULL, chociaż zapytanie nie ma wartości NULL.