0

I am currently using EF Core version 3.1.32 due to .NET Framework compatibility and am experiencing the following problem with eager loading…

I have the following (simplified) model:

class BaseType {
    String id { get; set; } = “Default”
}

class Product : BaseType {
    Toolset toolset { get; set; } = new Toolset();
}

class Toolset : BaseType {}

Tables are properly being created for Product (Products) and Toolset (Toolsets). The relationship is N:1. I am now saving the following data to the database:

Toolset toolset = new Toolset();
toolset.id = “Toolset 1”;

Product product1 = new Product();
product.id = “Product 1”;
product.toolset = toolset;

Product product1 = new Product();
product.id = “Product 2”;
product.toolset = toolset;

The database entries are properly being created with both products having a foreign key to the first (and only) toolset.

Now I want to eagerly load the two products together with the toolset from the database. This works perfectly fine when using separate contexts:

Product prod1 = new Context().Products.Include(e => e.toolset).Where(e => e.id == “Product 1”)
Console.WriteLine(prod1.toolset.id); // prints “Toolset 1”

Product prod2 = new Context().Products.Include(e => e.toolset).Where(e => e.id == “Product 2”)
Console.WriteLine(prod2.toolset.id); // prints “Toolset 1”

Now when I try to load the two products via same context, the reference to Toolset of the second query does not seem to get resolved:

Context ctx = new Context();

Product prod1 = ctx.Products.Include(e => e.toolset).Where(e => e.id == “Product 1”)
Console.WriteLine(prod1.toolset.id); // prints “Toolset 1”

Product prod2 = ctx.Products.Include(e => e.toolset).Where(e => e.id == “Product 2”)
Console.WriteLine(prod2.toolset.id); // prints “Default”

Does anybody have an explanation for that? Why is the reference of prod2 to toolset not resolved to object with ID “Toolset 1”?

Additional info:

EF Core version: 3.1.32

Database provider: Microsoft.EntityFrameworkCore.SqlServer

Target framework: .NET Framework 4.7.2

Operating system: Windows 10 64-Bit

IDE: Visual Studio 2019 (16.11)

Explicit loading (via Load()) works fine. It also seems to be working as expected after replacing Include with IncludeOptimized.

Progman
  • 16,827
  • 6
  • 33
  • 48
  • 2
    Remove ` = new Toolset();` from the class property. And as a rule of thumb, *never* initialize *reference* navigation properties because that breaks EF Core loading behaviors (as you already saw) – Ivan Stoev Jan 28 '23 at 11:58
  • I'll be very curious to see if the initialization actually interferes with the eager load, that seems like it would be a bug with EF Core 3.1 if that were the case. Normally I wouldn't initialize singular navigation properties, but I commonly recommend initializing collections so that new entities with child collections are ready to use. – Steve Py Jan 29 '23 at 08:22
  • @StevePy This has been discussed many times, starting with EF and including EF Core. Collection navigation properties - do initialize if you wish, but reference navigation properties - never initialize. That's it. Simple. Loading methods (lazy, explicit, eager) and EF Core versions doesn't matter. – Ivan Stoev Jan 29 '23 at 08:40
  • @IvanStoev gave the right answer. Not initializing navigation properties indeed did the trick! – CiNcH83 Jan 30 '23 at 05:46

0 Answers0