2015-05-12 6 views
11

Eine Abfrage für ein Raster in einer Entity Framework-gestützten .NET-Webanwendung, an der ich gerade arbeite, ergab einen 500-Fehler (The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.), wenn das Rasterzeilenobjekt in einer bestimmten Eins-zu-Viele-Beziehung keine untergeordneten Elemente enthält . Die Null kam auf eine nicht verwandte Ganzzahleigenschaft zurück. Erstaunlicherweise machte die Umkehrung der Reihenfolge der zwei unabhängigen Let-Anweisungen im Linq-Ausdruck den Fehler weg.Warum ist die Reihenfolge der LET-Anweisungen in dieser Entity Framework-Abfrage wichtig?

Das heißt, wenn es nur ein Widget (ID: 1, CreatedOn: some Datumzeit) ist, die keine Balken hat und ein Foo (fValue: 96)

from w in Widgets.OrderBy(w => w.CreatedOn) 
let foo = w.Foos.FirstOrDefault() 
let bar = w.Bars.FirstOrDefault() 
select new { w.WidgetID, foo.fValue } 

oder

from w in Widgets 
let bar = w.Bars.FirstOrDefault() 
let foo = w.Foos.FirstOrDefault() 
orderby w.CreatedOn 
select new { w.WidgetID, foo.fValue } 

gibt {WidgetID: 1, fValue: 96} wie erwartet, aber

from w in Widgets.OrderBy(w => w.CreatedOn) 
let bar = w.Bars.FirstOrDefault() 
let foo = w.Foos.FirstOrDefault() 
select new { w.WidgetID, foo.fValue } 

kommt zurück mit {WidgetID: 1, fValue: NULL} was natürlich Abstürze weil Foo.fValue eine Ganzzahl ist.

Alle drei Ausdrücke erzeugen leicht unterschiedliche SQL-Abfragen unter Entity Framework, die ich erwarten würde - die fehlerhafte Ausdruck enthält die Klausel

... 
(SELECT TOP (1) 
    [Extent7].[fValue] AS [fValue] 
    FROM (SELECT TOP (1) [Extent6].[BarID] AS [BarID] 
     FROM [dbo].[Bars] AS [Extent6] 
     WHERE [Extent1].[WidgetID] = [Extent6].[bWidgetID]) AS [Limit5] 
    CROSS JOIN [dbo].[Foos] AS [Extent7] 
    WHERE [Extent1].[WidgetID] = [Extent7].[fWidgetID]) AS [C1] 
... 

die meiner Meinung nach ist der Täter (0 Bars gekreuzt mit 1 Foo = 0 Ergebnisse). Also verstehe ich das "Wie" des Fehlers; Was mich erreicht ist, dass ich keine Ahnung habe warum die Reihenfolge der LETs oder ob ich OrderBy mit einem Linq-Methode Aufruf vs Linq Ausdruck sollte einen Unterschied machen.

Hier ist die reduzierte Tabellenschema/Daten, wenn Sie selbst experimentieren wollen:

create table Widgets (
    WidgetID int not null primary key, 
    CreatedOn datetime not null 
)  
insert Widgets values (1, '1995-02-03') 

create table Foos (
    FooID int not null primary key, 
    fWidgetID int not null references Widgets (WidgetID), 
    fValue int not null 
) 
insert Foos values (7, 1, 96) 

create table Bars (
    BarID int not null primary key, 
    bWidgetID int not null references Widgets (WidgetID), 
    bValue int not null 
) 

Können Sie erklären, warum diese drei Ausdrücke sind nicht logisch äquivalent in Entity Framework?

+1

Ich glaube, Sie haben gerade einen Fehler in EF gefunden. – Wasp

Antwort

1

Ich glaube, dass dies ein Fehler im Zusammenhang mit diesem bekannten Entity Framework-Problem ist: https://entityframework.codeplex.com/workitem/1196. Je nach Problem wird bei der Verwendung von order by, let und der Abfragebaum in eine fehlerhafte SQL-Abfrage kompiliert.

Leider ist das Problem fast zwei Jahre alt, so dass dieser spezielle Fehler für das EF-Team keine hohe Priorität hat. Vielleicht wird es in EF7 behoben werden!

+0

Nun, das ist bedauerlich. –

Verwandte Themen