Feature request: reload entity with all dependencies
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
### What problem are you trying to solve?
My code:
```C#
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace EfCoreReloadEntity;
public class Program
{
public static async Task Main(params string[] args)
{
IHost host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddDbContext(builder =>
{
builder.UseNpgsql("Host=localhost;Port=7435;Database=testdb;Username=admin;Password=testpass")
.UseSnakeCaseNamingConvention();
});
})
.Build();
await LoadAndReloadEntity(host);
}
public static async Task LoadAndReloadEntity(IHost host)
{
using var scope = host.Services.CreateScope();
var provider = scope.ServiceProvider;
var context = provider.GetRequiredService();
Product product = context.Set().First(x => x.Id == 1);
await context.Database.ExecuteSqlRawAsync("update products set name = 'Product-2' where products.id = 1");
await context.Database.ExecuteSqlRawAsync("INSERT INTO items (id, product_id, size) VALUES (3, 1, 40);");
try
{
product.Name = "Product-3";
await context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
var entries = ex.Entries;
if (entries.Count != 1)
throw;
EntityEntry entry = entries[0];
if (entry.Entity != product)
throw;
await entry.ReloadAsync();
Product reloadedProduct = (Product)entry.Entity;
if (reloadedProduct != product)
throw;
//return 2 items but product contains 3 items after execution raw sql
Console.WriteLine(reloadedProduct.Items.Count);
}
}
}
public class Product
{
private readonly uint _version;
public required int Id { get; set; }
public required string Name { get; set; }
public List Items { get; set; }
}
public class ProductItem
{
public int Id { get; set; }
public int Size { get; set; }
public int ProductId { get; set; }
}
public class MyContext : DbContext
{
public DbSet Product { get; set; }
public DbSet Items { get; set; }
public MyContext(DbContextOptions options)
: base(options)
{
Database.EnsureDeleted();
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var product = new Product()
{
Id = 1,
Name = "Product-1",
Items = new List()
};
List items = new()
{
new ProductItem()
{
Id = 1,
Size = 30,
ProductId = 1
},
new ProductItem()
{
Id = 2,
Size = 35,
ProductId = 1
}
};
modelBuilder.Entity().HasData(product);
modelBuilder.Entity().HasData(items);
modelBuilder.Entity(builder =>
{
builder.ToTable("products");
builder
.Navigation(p => p.Items)
.AutoInclude();
builder
.Property(p => p.Name)
.HasColumnName("name");
builder
.Property("_version")
.IsRowVersion();
});
}
}
```
Product object is an aggregate. I'm using autoinclude but want to reload entire product with all dependencies. But EF Core doesn't let to reload it with dependencies. I know that I can remove object from context and load new Product. But it will be new object.
In this case I have to return new object to calling method.
Lazy loading also is not good for me because I'm using repository pattern and object can contains many dependencies.
### Describe the solution you'd like
I want to have a solution to reload entire aggregate with dependencies without creating new aggregate.
it might look like this:
```C#
await entry.ReloadAsync(loadDependencies: true);
```
Contributor guide
Assessment
This issue has not been assessed yet.