2012-02-14 6 views
6

Wygląda jak głupie pytanie, ale po prostu nie rozumiem. Moja jednostka:Wyrażenie Linq z nullable

public class Page 
{ 
    public int Id { get; set; } 
    //... 
    public int? ParentId { get; set; } 
} 

W sterowniku:

db.Pages.First(x => x.ParentId == null); 

działa zgodnie z oczekiwaniami (zwraca jakiś element). Ale:

int? test = null; 
db.Pages.First(x => x.ParentId == test); 

Zgłasza Sequence contains no elements

Co mnie ominęło?

+1

Czy używasz linq-to-entity? Nie ma to nic wspólnego z asp.net-mvc? – gideon

Odpowiedz

10

Wierzę, że w niektórych dostawach LINQ występuje dziwność wokół zer. Spróbuj:

var query = db.Pages.First(x => (test != null && x.ParentId == test) || 
           (test == null && x.ParentId == null)); 

Ewentualnie użyć różnych zapytań do różnych sytuacjach:

var query = test == null ? db.Pages.First(x => x.ParentId == null) 
         : db.Pages.First(x => x.ParentId == test); 

Zasadniczo jest to spowodowane SQL Traktuje NULL jako nierówne sobie tak:

WHERE X = Y 

nadal nie jeśli oba X i Y są wartościami pustymi. Używanie partycji == null (z literowym null) wymusza konwersję na ISNULL lub bez względu na to, jaki jest odpowiednik SQL.

Zgadzam się, że to ból, a ktoś inny może mieć lepsze obejście tego problemu, ale to może ci pomóc.

+2

_better workaround_ Przenieś się do przyzwoitego dostawcy LINQ, ling NH ... – gdoron

1

Spróbuj tego (modyfikowany zgodnie z komentarzem gdoron za Jest teraz dokładnie co Gideon pisał, więc proszę przyjąć jego zamiast kopalni.):

int? test = null; 
if(test.HasValue) { 
    db.Pages.First(x => x.ParentId == test.Value); 
} else { 
    db.Pages.First(x => x.ParentId == null); 
} 
+2

Nie będzie działać. 'Wartość - wartość bieżącego obiektu Nullable (Of T), jeśli właściwość HasValue ma wartość true. ==> Wyjątek jest zgłaszany, jeśli właściwość HasValue ma wartość false. <== ' – gdoron

+0

Tak, dzięki za podpowiedź. –

+0

thx za to rozwiązanie, ale chciałem tylko zrozumieć, że dziwność LINQ – Wonder

2

Można zrobić coś takiego jako obejście:

int? test = null; 
if(test.HasValue) { 
db.Pages.First(x => x.ParentId == test.Value); 
} else { 
db.Pages.First(x => x.ParentId == null); 
} 

jestem zakładając, ponieważ int? faktycznie jest dostawcą Nullable<int> nasze LINQ-podmioty nie porównując rzeczy prawo.