-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
System.NullReferenceException thrown #21398
Comments
Wonder if OData has been tested with EF Core 5? |
Yes, there could be such a maturity problem or the other way around, that EF Core 5 is not being tested with OData. I have made one more observations: If I query the whole collection of bikes, i.e. do not specify the key, I get the same exception, i.e.: BUT if the Bikes collection is empty, i.e. the Bikes table in the database has no rows, the query executes correctly without any exception!! To me it looks immature, i.e. simple cases you should expect to occur over and over again have not been taken into account. |
Please share a runnable repro code. Possibly without using OData. |
Now I obviously don't know if you know OData, but do you know if I can somehow get the query which OData produces so I can be sure I query EF Core the same way but eliminates OData, because I just issue the query which OData would have been producing? Can EF Core for instance log the query it receives because I can also take it from the recipient side of course? |
I will wait for someone to respond to OData/WebApi#2206 and isolate EF Core issue if any. |
@smitpatel As far as I know, I have now published a tiny sample to Github: https://github.com/henrikdahl8240/CastProblem20200624 You may see the few simple steps in todo.txt, which you can just copy/paste to your machine. Can you see the problem now? |
Unfortunately .NET 5.0 Preview 6 results in the same exception. I hope you may take a look into it. There are only a few lines of code in the sample and it will take you very short time to familiarize yourself with it. |
I can reproduce this, but I don't know how to get the IQueryable that OData is generating. Does anyone know where to set a breakpoint or something else that can be done to figure out what query OData is generating? |
Can the following log help you? info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 5.0.0-preview.5.20278.2 initialized 'CastProblemDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: using lazy-loading proxies CommandTimeout=600
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (75ms) [Parameters=[@__TypedProperty_1='?' (Size = 4000)], CommandType='Text', CommandTimeout='600']
SELECT [b].[ID], [b].[Discriminator], [b].[Version], [b].[CategoryParentID], [t].[c], [t].[c0], [t].[ID], [t].[c1], [t].[Version], CASE
WHEN [b1].[Discriminator] = CAST(8 AS tinyint) THEN N'CastProblem20200624.BikeShop_Good__Local__BikeShop_BibliographicalRecordInventory'
WHEN [b1].[Discriminator] = CAST(7 AS tinyint) THEN N'CastProblem20200624.BikeShop_Good__Local__BikeShop'
WHEN [b1].[Discriminator] = CAST(0 AS tinyint) THEN N'CastProblem20200624.BikeShop_Good_Z3950Target'
ELSE N'CastProblem20200624.BikeShop_Good'
END, [b1].[ID], [b1].[Version], CASE
WHEN [b1].[Discriminator] = CAST(0 AS tinyint) THEN N'ISIL_Number'
ELSE NULL
END, [b1].[ISIL_Number], NULL, [b1].[BikeShopID], [b1].[CategoryID], [b1].[Discriminator], [b1].[Preferred_PropertyUri_For_BibliographicalRecord], [b1].[Target_BikeShopID], [b1].[Target_BikeShop_BibliographicalRecordInventoryID]
FROM [BikeShop_GoodCategorys] AS [b]
LEFT JOIN (
SELECT @__TypedProperty_1 AS [c], N'ID' AS [c0], [b0].[ID], N'Version' AS [c1], [b0].[Version], [b0].[CategoryParentID]
FROM [BikeShop_GoodCategorys] AS [b0]
WHERE [b0].[Discriminator] = CAST(1 AS tinyint)
) AS [t] ON [b].[ID] = [t].[CategoryParentID]
LEFT JOIN [BikeShop_Goods] AS [b1] ON [b].[ID] = [b1].[CategoryID]
WHERE [b].[Discriminator] = CAST(1 AS tinyint)
ORDER BY [b].[ID], [t].[ID], [b1].[ID] |
We need actual LINQ query. The error message indicates that the shaper created for materializing collection has null ref error. We cannot figure it out from SQL. |
For the "bad" case as below:
We have the follow linq "Debug view": .New Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectAllAndExpand`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]()
{
ModelID = .Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty,
Instance = $$it,
UseInstanceForProperties = True,
Container = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedPropertyWithNext0`1[System.Collections.Generic.IEnumerable`1[Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]]]()
{
Name = "CategoryChildren",
Value = .Call System.Linq.Enumerable.Select(
($$it .As CastProblem20200624.BikeShop_GoodCategory).CategoryChildren,
.Lambda #Lambda1<System.Func`2[CastProblem20200624.BikeShop_GoodCategory_NonRoot,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]]>)
,
Next0 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.Collections.Generic.IEnumerable`1[Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSomeAndInheritance`1[CastProblem20200624.BikeShop_Good]]]()
{
Name = "Contents",
Value = .Call System.Linq.Enumerable.Select(
($$it .As CastProblem20200624.BikeShop_GoodCategory).Contents,
.Lambda #Lambda2<System.Func`2[CastProblem20200624.BikeShop_Good,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSomeAndInheritance`1[CastProblem20200624.BikeShop_Good]]>)
}
}
}
.Lambda #Lambda1<System.Func`2[CastProblem20200624.BikeShop_GoodCategory_NonRoot,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]]>(CastProblem20200624.BikeShop_GoodCategory_NonRoot $$it)
{
.New Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]()
{
ModelID = .Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty,
Container = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedPropertyWithNext0`1[System.Nullable`1[System.Guid]]()
{
Name = "ID",
Value = (System.Nullable`1[System.Guid])($$it .As CastProblem20200624.BikeShop_GoodCategory).ID,
Next0 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.Byte[]](){
Name = "Version",
Value = ($$it .As CastProblem20200624.BikeShop_GoodCategory).Version
}
}
}
}
.Lambda #Lambda2<System.Func`2[CastProblem20200624.BikeShop_Good,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSomeAndInheritance`1[CastProblem20200624.BikeShop_Good]]>(CastProblem20200624.BikeShop_Good $$it)
{
.New Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSomeAndInheritance`1[CastProblem20200624.BikeShop_Good]()
{
ModelID = .Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty,
InstanceType = .If (
$$it .Is CastProblem20200624.BikeShop_Good__Local__BikeShop_BibliographicalRecordInventory
) {
"CastProblem20200624.BikeShop_Good__Local__BikeShop_BibliographicalRecordInventory"
} .Else {
.If (
$$it .Is CastProblem20200624.BikeShop_Good__Local__BikeShop
) {
"CastProblem20200624.BikeShop_Good__Local__BikeShop"
} .Else {
.If (
$$it .Is CastProblem20200624.BikeShop_Good__Local
) {
"CastProblem20200624.BikeShop_Good__Local"
} .Else {
.If (
$$it .Is CastProblem20200624.BikeShop_Good_Z3950Target
) {
"CastProblem20200624.BikeShop_Good_Z3950Target"
} .Else {
"CastProblem20200624.BikeShop_Good"
}
}
}
},
Container = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedPropertyWithNext2`1[System.Nullable`1[System.Guid]]()
{
Name = "ID",
Value = (System.Nullable`1[System.Guid])$$it.ID,
Next0 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.Byte[]](){
Name = "Version",
Value = $$it.Version
},
Next1 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.String](){
Name = .If (
$$it .Is CastProblem20200624.BikeShop_Good_Z3950Target
) {
"ISIL_Number"
} .Else {
null
},
Value = ($$it .As CastProblem20200624.BikeShop_Good_Z3950Target).ISIL_Number
},
Next2 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.String](){
Name = .If (
$$it .Is CastProblem20200624.BikeShop_Good__Local
) {
"Preferred_PropertyUri_For_BibliographicalRecord"
} .Else {
null
},
Value = ($$it .As CastProblem20200624.BikeShop_Good__Local).Preferred_PropertyUri_For_BibliographicalRecord
}
}
}
} For the "good" case as below:
We have the follow linq "Debug view": .New Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectAllAndExpand`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]()
{
ModelID = .Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty,
Instance = $$it,
UseInstanceForProperties = True,
Container = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedPropertyWithNext0`1[System.Collections.Generic.IEnumerable`1[Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]]]()
{
Name = "CategoryChildren",
Value = .Call System.Linq.Enumerable.Select(
($$it .As CastProblem20200624.BikeShop_GoodCategory).CategoryChildren,
.Lambda #Lambda1<System.Func`2[CastProblem20200624.BikeShop_GoodCategory_NonRoot,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]]>)
,
Next0 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.Collections.Generic.IEnumerable`1[Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[CastProblem20200624.BikeShop_Good]]]()
{
Name = "Contents",
Value = .Call System.Linq.Enumerable.Select(
($$it .As CastProblem20200624.BikeShop_GoodCategory).Contents,
.Lambda #Lambda2<System.Func`2[CastProblem20200624.BikeShop_Good,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[CastProblem20200624.BikeShop_Good]]>)
}
}
}
.Lambda #Lambda1<System.Func`2[CastProblem20200624.BikeShop_GoodCategory_NonRoot,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]]>(CastProblem20200624.BikeShop_GoodCategory_NonRoot $$it)
{
.New Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[CastProblem20200624.BikeShop_GoodCategory_NonRoot]()
{
ModelID = .Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty,
Container = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedPropertyWithNext0`1[System.Nullable`1[System.Guid]]()
{
Name = "ID",
Value = (System.Nullable`1[System.Guid])($$it .As CastProblem20200624.BikeShop_GoodCategory).ID,
Next0 = .New Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[System.Byte[]](){
Name = "Version",
Value = ($$it .As CastProblem20200624.BikeShop_GoodCategory).Version
}
}
}
}
.Lambda #Lambda2<System.Func`2[CastProblem20200624.BikeShop_Good,Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[CastProblem20200624.BikeShop_Good]]>(CastProblem20200624.BikeShop_Good $$it)
{
.New Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[CastProblem20200624.BikeShop_Good](){
ModelID = .Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty,
Instance = $$it,
UseInstanceForProperties = True
}
} |
@smitpatel See the above linq expression (debug view), please let me know you need others. |
Can you get |
I use the following codes: #if NETCOREAPP3_1
string abc = new ExpressionPrinter().Print(projectionExpression);
Console.WriteLine(abc);
#endif here we are: For "bad" case:new SelectAllAndExpand<BikeShop_GoodCategory_NonRoot>{
ModelID = TypedLinqParameterContainer<string>.TypedProperty,
Instance = $it,
UseInstanceForProperties = True,
Container = new NamedPropertyWithNext0<IEnumerable<SelectSome<BikeShop_GoodCategory_NonRoot>>>{
Name = "CategoryChildren",
Value = ($it as BikeShop_GoodCategory).CategoryChildren
.Select($it => new SelectSome<BikeShop_GoodCategory_NonRoot>{
ModelID = TypedLinqParameterContainer<string>.TypedProperty,
Container = new NamedPropertyWithNext0<Nullable<Guid>>{
Name = "ID",
Value = (Nullable<Guid>)($it as BikeShop_GoodCategory).ID,
Next0 = new NamedProperty<byte[]>{
Name = "Version",
Value = ($it as BikeShop_GoodCategory).Version
}
}
}
),
Next0 = new NamedProperty<IEnumerable<SelectSomeAndInheritance<BikeShop_Good>>>{
Name = "Contents",
Value = ($it as BikeShop_GoodCategory).Contents
.Select($it => new SelectSomeAndInheritance<BikeShop_Good>{
ModelID = TypedLinqParameterContainer<string>.TypedProperty,
InstanceType = ($it is BikeShop_Good__Local__BikeShop_BibliographicalRecordInventory) ? "CastProblem20200624.BikeShop_Good__Local__BikeShop_BibliographicalRecordInventory" : ($it is BikeShop_Good__Local__BikeShop) ? "CastProblem20200624.BikeShop_Good__Local__BikeShop" : ($it is BikeShop_Good__Local) ? "CastProblem20200624.BikeShop_Good__Local" : ($it is BikeShop_Good_Z3950Target) ? "CastProblem20200624.BikeShop_Good_Z3950Target" : "CastProblem20200624.BikeShop_Good",
Container = new NamedPropertyWithNext2<Nullable<Guid>>{
Name = "ID",
Value = (Nullable<Guid>)$it.ID,
Next0 = new NamedProperty<byte[]>{
Name = "Version",
Value = $it.Version
}
,
Next1 = new NamedProperty<string>{
Name = ($it is BikeShop_Good_Z3950Target) ? "ISIL_Number" : null,
Value = ($it as BikeShop_Good_Z3950Target).ISIL_Number
}
,
Next2 = new NamedProperty<string>{
Name = ($it is BikeShop_Good__Local) ? "Preferred_PropertyUri_For_BibliographicalRecord" : null,
Value = ($it as BikeShop_Good__Local).Preferred_PropertyUri_For_BibliographicalRecord
}
}
}
)
}
}
} for the "Good" casenew SelectAllAndExpand<BikeShop_GoodCategory_NonRoot>{
ModelID = TypedLinqParameterContainer<string>.TypedProperty,
Instance = $it,
UseInstanceForProperties = True,
Container = new NamedPropertyWithNext0<IEnumerable<SelectSome<BikeShop_GoodCategory_NonRoot>>>{
Name = "CategoryChildren",
Value = ($it as BikeShop_GoodCategory).CategoryChildren
.Select($it => new SelectSome<BikeShop_GoodCategory_NonRoot>{
ModelID = TypedLinqParameterContainer<string>.TypedProperty,
Container = new NamedPropertyWithNext0<Nullable<Guid>>{
Name = "ID",
Value = (Nullable<Guid>)($it as BikeShop_GoodCategory).ID,
Next0 = new NamedProperty<byte[]>{
Name = "Version",
Value = ($it as BikeShop_GoodCategory).Version
}
}
}
),
Next0 = new NamedProperty<IEnumerable<SelectAll<BikeShop_Good>>>{
Name = "Contents",
Value = ($it as BikeShop_GoodCategory).Contents
.Select($it => new SelectAll<BikeShop_Good>{
ModelID = TypedLinqParameterContainer<string>.TypedProperty,
Instance = $it,
UseInstanceForProperties = True
}
)
}
}
} |
@smitpatel is the "$it" problem? It seems "$it" used in each level? |
Is |
No, it was not and it is obviously a mistake. Its super class(es) and its sub classes are mapped, but not the class itself. After mapping it, everything works fine, also in the real solution, which this is an excerpt of. I am porting a solution from .NET Framework and EF 6.4 to .NET 5.0 and EF Core 5.0. EF 6.4 had a different strategy as it could to some extent automatically discover and include some classes to the model. Therefore the issue did not occur in scope of .NET Framework and EF 6.4. I think it's really difficult to spot such a case, for instance because the error message is of no help, except you can guess, that the null reference exception denotes that a mapping is missing, but it could denote all sorts of things. If you for instance try to $select an owned object, you get an excepton which tells, that either the owner must be included or you must use AsNoTracking(). This is quite easy to understand, however it's very annoying, that you cannot $select an owned type when tracking is being used and the owner is not being included. Thank you for your assistance. It was really valuable to me. Perhaps others may benefit from this correlation, i.e. null reference exception and lack of mapping. |
@henrikdahl8240 Welcome. Glad to see that. Anyway, we also value from your questions, concerns. Thanks. |
Thank you very much. I think that it could be very valuable, if you would make a dedicated error message like e.g.: The new exception could be named something like "ClassNotFoundInTheRepositoryOfClassesException" or simply "ClassNotMappedException", but perhaps you have some other preferences for names. You could make the exception System.NullReferenceException to be the inner exception for the dedicated exception. Had there been such a dedicated error message, I would obviously have continued right away. |
The thing is, there is no way to know what is the cause of NullRef Exception. We evaluated user code which threw null ref. Just like any other user written code, there is only one reason for null ref but there is infinite reasons leading to a null ref. |
OK. I thought the general business context of what is going on in the specific feature area could have told that. So it's a bit hard, of course. So regarding "user code", you actually mean code in Microsoft OData because I don't think there's any of my code, which gets invoked in this case? The lack of description in the error message just lets the user in a rather difficult situation as he obviously would like to make things to work well as efficiently and effective as possible. |
In the query EF sees |
I have an OData query like:
...Bikes(1)/ns.MountainBike?$expand=Children($select=P1,P2,ns.A/P3,ns.B/P4)
Some of the instances in Children are of type A, none are of type B.
Unfortunately this exception is being thrown:
If I do this query instead, it works fine:
...Bikes(1)/ns.MountainBike?$expand=Children($select=P1,P2,ns.A/P3)
If I do this query, I get the same exception:
...Bikes(1)/ns.MountainBike?$expand=Children($select=ns.B/P4)
Therefore it looks to me like if I use a cast for a type of which no instances match, I get the exception.
Is this enough information, because it takes a lot of time for me to make a concrete sample which demonstrates it?
I use Microsoft.AspNetCore.OData 7.4.1 and .Net 5.0 preview 5.
The text was updated successfully, but these errors were encountered: