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?
Ich glaube, Sie haben gerade einen Fehler in EF gefunden. – Wasp