2010-12-15 12 views
11

Mam zapytanie metoda tak:Unikaj "obiektu Nullable musi mieć wartość." w LINQ-SQL

public IList<BusinessObject> GetBusinessObject(Guid? filterId) 
{ 
    using (var db = new L2SDataContext()) 
    { 
     var result = from bo in db.BusinessObjects 
        where (filterId.HasValue) 
           ? bo.Filter == filterId.value 
           : true 
        orderby bo.Name 
        select SqlModelConverters.ConvertBusinessObject(bo); 
     return result.ToList(); 
    } 
} 

W czasie wykonywania tego rzuca System.InvalidOperationException: Nullable object must have a value.

Patrząc na Debugger, problem jest moja Gdzie klauzuli: LINQ Aby próbach SQL aby przekonwertować całą zawartość na SQL, więc nawet jeśli filterId ma wartość NULL, nadal będzie próbował uzyskać dostęp do właściwości filterId.value.

Myślałem/mam nadzieję, że kompilator C/CLR oceni, że klauzula where jest blokiem kodu i wysyła tylko jedną z dwóch gałęzi Linq To SQL, ale tak nie działa.

Moja refactored wersja działa, ale nie jest bardzo elegancki:

public IList<BusinessObject> GetBusinessObject(Guid? filterId) 
{ 
    using (var db = new L2SDataContext()) 
    { 
     var temp = from bo in db.BusinessObjects select bo; 
     if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value); 
     var result = from t in temp 
        orderby t.Name 
        select SqlModelConverters.ConvertBusinessObject(bo); 
     return result.ToList(); 
    } 
} 

wiem, że Lazy-ocena będzie upewnić się, że tylko jeden jest naprawdę wysłał zapytanie, ale o ten obiekt w temp nie jest to, że świetnie, naprawdę.

Odpowiedz

16

Próbowałaś:

where filterId == null || t.Filter == filterId 
+1

Oh wow, który działa doskonale! Oszczędza mi to przed używaniem nieco nieczytelnego operatora trzeciorzędowego i rozwiązuje rzeczywisty wyjątek spowodowany niepotrzebnym dostępem do właściwości filterId.Value, a nie tylko filtrem filterId. –

1

Twoja poprawka jest poprawna. Próbujesz skutecznie budować zapytanie dynamicznie, w oparciu o dane wejściowe funkcji. Warto mimo wszystko pominąć klauzulę where, zamiast dostarczać WHERE TRUE. Gdybym pisał to zapytanie, sam bym podszedł z Twoją stałą wersją.

To nie jest tak piękne, jak użycie słów kluczowych w języku, ale nadal jest to właściwy sposób podejścia do zapytania w mojej opinii.

Powiązane problemy