dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.77k stars 3.18k forks source link

Why is EFCore6 throwing NullReferenceException when adding entity/entities? It is working in EFCore5. #26644

Closed frankfajardo closed 2 years ago

frankfajardo commented 2 years ago

Question: What is causing the NullReferenceException?

We have an active project which was started on ASP.NET 5 and EFCore 5.0. I'm investigating the move/migration to ASP.NET 6 and EFCore 6.0. The move to ASP.NET 6 (with EFCore 5.0) appears to be okay; the app is building and our tests are all passing still. But the move to EFCore 6.0 seems to be more challenging. II understand there are breaking changes between EFCore 5 and EFCore 6. However, I'm encountering this runtime error which I could not figure out the cause of. If only it gives me more info.

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.InitialFixup(InternalEntityEntry entry, Boolean fromQuery)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.StateChanged(InternalEntityEntry entry, EntityState oldState, Boolean fromQuery)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.StateChanged(InternalEntityEntry entry, EntityState oldState, Boolean fromQuery)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.FireStateChanged(EntityState oldState)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityState(InternalEntityEntry entry, EntityState entityState)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityStates(IEnumerable`1 entities, EntityState entityState)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.AddRange(IEnumerable`1 entities)
   at XXX.Application.UnitTests.Products.ListProductsUnitTests.<ListProducts_GivenMultipleSimulatorFilters_ShouldReturnProductsWithAnyOfTheSimulators>d__18.MoveNext() in C:\Users\...\XXX.Application.UnitTests\Products\ListProductsUnitTests.cs:line 279

It is failing at this:

dbContext.Products.AddRange(products); // dbContext is a in-memory db

The entity model Product is this:

    public class Product : AuditableEntity
    {
        public Guid OrganizationId { get; set; }

        public Organization? Organization { get; set; }

        public Guid ProductFamilyId { get; set; }

        public ProductFamily? ProductFamily { get; set; }

        public string Name { get; set; } = null!;

        public string Slug { get; set; } = null!;

        public string? Description { get; set; }

        public ProductType Type { get; set; }

        public bool IsSubscription { get; set; }

        public ICollection<Discount> Discounts { get; set; } = new List<Discount>();

        public ICollection<Bundle> Bundles { get; set; } = new List<Bundle>();

        public ICollection<Price> Prices { get; set; } = new List<Price>();

        public ICollection<Tag> Tags { get; set; } = new List<Tag>();

        public ICollection<Tag> Simulators { get; set; } = new List<Tag>();

        public ICollection<ProductAccess>? ProductAccesses { get; set; }

        public ICollection<Component>? Components { get; set; }
    }

Running the test in debug mode, the data being saved has this (minimal) test data: image

What is causing the NullReferenceException? I already tried to assign values to all nullable properties of the Product entity but it still complains. I was only running one specific test so I don't think a shared dbContext is an issue. Besides, the unit test class creates its own instance of the dbContext.

The same test runs without failure on EFCore 5.

I have re-generated our migration scripts using the dotnet-ef 6.0.0 but I get same results.

EF Core version: 6.0 Database provider: InMemory, Postgresql Target framework: .NET 6.0 Operating system: Windows 11 IDE: Visual Studio 2022

ajcvickers commented 2 years ago

@frankfajardo Please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

frankfajardo commented 2 years ago

Hi @ajcvickers , I will close this issue. We have multiple relationships between our two entities (Product and Tag entities) similar to this SO question which was okay with EFCore5 but not with EFCore6.. So we have added configuration in our OnModelCreating(). We can live with that.