dotnet / dotnet/efcore

Inconsistent behaviors when loading related entities explicitly with Query and Include

Open
#33,859 0 comments 0 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Explicit loading works fine when I want to load navigation properties of an (detached) entity.

But when my entities get complex and I try to call `Query` and `Include`s on a `CollectionEntry` to include navigation propertie on the items of the collection, which does not work as expected.

For example:

```csharp
using Microsoft.EntityFrameworkCore;
A a;
using (var db = new TheDbContext())
{
db.Database.EnsureCreated();
if (!db.As.Any())
{
db.Add(new A()
{
Bs =
[
new B() { C=new() },
new B() { C=new() },
new B() { C=new() },
]
});
db.SaveChanges();
}

a = db.As.First()!;
}

JustLoadCollection(a);
LoadAndInclude(new A() { Id = a.Id });
LoadAndIncludeWhenTracked(new A() { Id = a.Id });

void JustLoadCollection(A a)
{
using var db = new TheDbContext();
db.Entry(a).Collection(a => a.Bs).Load();
Console.WriteLine(a.Bs.Count);
}

void LoadAndInclude(A a)
{
using var db = new TheDbContext();
db.Entry(a).Collection(a => a.Bs).Query().Include(b => b.C).Load();
Console.WriteLine(a.Bs.Count);
}

void LoadAndIncludeWhenTracked(A a)
{
using var db = new TheDbContext();
db.Entry(a).State = EntityState.Unchanged;
db.Entry(a).Collection(a => a.Bs).Query().Include(b => b.C).Load();
Console.WriteLine(a.Bs.Count);
}

class TheDbContext : DbContext
{
public DbSet As { set; get; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=db.sqlite");
}
}

class A
{
public Guid Id { get; set; } = Guid.NewGuid();
public ICollection Bs { get; set; } = new List();
}

class B
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid AId { set; get; }
public C C { get; set; } = null!;
}

class C
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid BId { set; get; }
public int N { set; get; }
}
```

Only `LoadAndIncludeWhenTracked` populate the collection and related data of `a`. While `JustLoadCollection` can also load the collection and `LoadAndInclude` load nothing into `a` at all.

**If I want `db.Entry(a).Collection(a => a.Bs).Query().Include(b => b.C).Load()` work, is `LoadAndIncludeWhenTracked` the proper way?**

EF Core version: 8.0.6
Database provider: Microsoft.EntityFrameworkCore.Sqlite
Target framework: .NET 8.0

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.