Skip to content

Breaking Change in 8.0.4: System.InvalidOperationException: The data is NULL at ordinal 0. This method can't be called on NULL values. Check using IsDBNull before calling. #33547

Closed
@eisbaer66

Description

@eisbaer66

File a bug

I have run into this problem when upgrading from 8.0.3 to 8.0.4.
I have a Parent type that contains an optional Child.

public class Parent
{
	public int Id { get; set; }
	public Child? Child { get; set; }
}

The Child contains a simple type, that is saved as a ComplexProperty.

public class Child
{
	public int Id { get; set; }
	public required Complex Complex { get; set; }
	public bool Deleted { get; set; }
}

There is a QueryFilter defined for the Child (simple bool property "Deleted").

public class ApplicationDbContext : DbContext
{
	public DbSet<Parent> Parents { get; set; }


	public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
		: base (options)
	{
	}

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		base.OnModelCreating (modelBuilder);

		modelBuilder.Entity<Child> ()
		            .ComplexProperty (x => x.Complex);

		modelBuilder.Entity<Child> ().HasQueryFilter (x => !x.Deleted);
	}
}

The Complex type contains a enum.

public class Complex
{
	public MyEnum Enum { get; set; }
}
public enum MyEnum
{
	None    = 0,
	Enabled = 1,
}

When I now try to query the enum coming from the Parent type though the Child and Complex types, I want the result to be null, if the (optional) Child is not set (is null).

var my_enum = db_context.Parents
                        .Select (p => p.Child != null ? (MyEnum?)p.Child.Complex.Enum : null)
                        .FirstOrDefault ();

But i get a InvalidOperationException instead.

Downgrading back to 8.0.3 restores the expected behavior again.

Include your code

I have created a small solution with one console project to reproduce the problem:
efcore-enum-in-optional-complex-property-with-queryfilter-repro.zip

It creates a sqlite database (deleting any existing "test.db" file beforehand) so you should be able to just run it (again and again) to reproduce the exception.

Stack traces

Unhandled exception. System.InvalidOperationException: An error occurred while reading a database value. The expected type was 'efcore_enum_in_optional_complex_property_repro.Entites.MyEnum' but the actual value was null.
 ---> System.InvalidOperationException: The data is NULL at ordinal 0. This method can't be called on NULL values. Check using IsDBNull before calling.
   at Microsoft.Data.Sqlite.SqliteValueReader.GetInt64(Int32 ordinal)
   at Microsoft.Data.Sqlite.SqliteValueReader.GetInt32(Int32 ordinal)
   at Microsoft.Data.Sqlite.SqliteDataReader.GetInt32(Int32 ordinal)
   at lambda_method31(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   --- End of inner exception stack trace ---
   at lambda_method31(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
   at lambda_method32(Closure, QueryContext)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at Program.<<Main>$>g__Act|0_2(<>c__DisplayClass0_0&) in %path-to-repos%\efcore-enum-in-optional-complex-property-with-queryfilter-repro\efcore-enum-in-optional-complex-property-repro\Program.cs:line 49
   at Program.<Main>$(String[] args) in %path-to-repos%\efcore-enum-in-optional-complex-property-with-queryfilter-repro\efcore-enum-in-optional-complex-property-repro\Program.cs:line 12

Include provider and version information

EF Core version: 8.0.4 (still works in 8.0.3)
Database provider: Microsoft.EntityFrameworkCore.Sqlite 8.0.4 (same error happens with Microsoft.EntityFrameworkCore.SqlServer 8.0.4)
Target framework: .NET 8.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.9.5

Activity

self-assigned this
on Apr 16, 2024
PjotrB

PjotrB commented on Apr 16, 2024

@PjotrB

I see that Microsoft.EntityFrameworkCore 8.0.4 is now "unlisted":
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore/8.0.4

Is that because of this issue?

Note that a couple of v8.0.4 packages are still listed, with a reference to Microsoft.EntityFrameworkCore 8.0.4, but they will fail to install or update. IMHO it would be better if all dependent packages would also be unlisted in such a situation.

dougclutter

dougclutter commented on Apr 16, 2024

@dougclutter

I see that Microsoft.EntityFrameworkCore 8.0.4 is now "unlisted": https://www.nuget.org/packages/Microsoft.EntityFrameworkCore/8.0.4

Is that because of this issue?

Note that a couple of v8.0.4 packages are still listed, with a reference to Microsoft.EntityFrameworkCore 8.0.4, but they will fail to install or update. IMHO it would be better if all dependent packages would also be unlisted in such a situation.

Agreed.

More importantly to us, where can we find information on why this package was unlisted? Should we hold off on upgrading to 8.0.4? Can we safely use Microsoft.EntityFrameworkCore/8.0.3 with other packages such as Microsoft.EntityFrameworkCore.Relational/8.0.4?

maumar

maumar commented on Apr 16, 2024

@maumar
Contributor

@PjotrB @dougclutter 8.0.4 is back up. Unlisting was not intentional, likely a glitch in our system. We are looking into the details, what exactly happened, but it should be safe to upgrade.

maumar

maumar commented on Apr 17, 2024

@maumar
Contributor

#32911 is the culprit. @eisbaer66 - you can make your scenario work on 8.0.4 by setting the following AppContext switch: "Microsoft.EntityFrameworkCore.Issue32911"

maumar

maumar commented on Apr 17, 2024

@maumar
Contributor

Problem is that upon applying LEFT JOIN operation, Enum value on the complex type is not marked as nullable. We have StructuralTypeProjectionExpression and we mark all the primitive properties as nullable, but for nested structures (like the complex type here) we only mark the shaper itself nullable, but the nested StructuralTypeProjectionExpression that is stored in the ValueBufferExpression is not touched.

In 8.0.3 we were storing all the properties of complex types in the flat structure, along with regular properties, so the nullabilities were set for all of them.

added this to the 8.0.x milestone on Apr 17, 2024
eisbaer66

eisbaer66 commented on Apr 17, 2024

@eisbaer66
Author

#32911 is the culprit. @eisbaer66 - you can make your scenario work on 8.0.4 by setting the following AppContext switch: "Microsoft.EntityFrameworkCore.Issue32911"

Can confirm that setting AppContext.SetSwitch("Microsoft.EntityFrameworkCore.Issue32911", true) allows this scenario in 8.0.4 👍

added a commit that references this issue on Apr 18, 2024

Fix to #33547 - Breaking Change in 8.0.4: System.InvalidOperationExce…

added a commit that references this issue on Apr 18, 2024

Fix to #33547 - Breaking Change in 8.0.4: System.InvalidOperationExce…

added
closed-fixedThe issue has been fixed and is/will be included in the release indicated by the issue milestone.
on Apr 18, 2024

18 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Breaking Change in 8.0.4: System.InvalidOperationException: The data is NULL at ordinal 0. This method can't be called on NULL values. Check using IsDBNull before calling. · Issue #33547 · dotnet/efcore