DKNet

Stage new entities found in collection navigations

Part of DKNet.EfCore.Extensions. Walk collection navigations from possible updating roots and add discovered new children in one batch.

Use the console-project setup in the Quick Start, then replace Program.cs with this example.

using Microsoft.EntityFrameworkCore;
using DKNet.EfCore.Extensions.Extensions;

using var connection = new Microsoft.Data.Sqlite.SqliteConnection("Data Source=:memory:");
connection.Open();
var o = new DbContextOptionsBuilder<DemoDb>();
o.UseSqlite(connection);
await using var db = new DemoDb(o.Options);
await db.Database.EnsureCreatedAsync();
var parent = new Item { Name = "Coffee" };
db.Add(parent);
await db.SaveChangesAsync();
db.ChangeTracker.AutoDetectChangesEnabled = false;
parent.Name = "Coffee beans";
db.Entry(parent).Property(x => x.Name).IsModified = true;
parent.Children.Add(new Child());
Console.WriteLine(db.GetNewEntitiesFromNavigations(db.Entry(parent)).Count()); // 1
Console.WriteLine(await db.AddNewEntitiesFromNavigations()); // 1: the child is considered new
db.ChangeTracker.AutoDetectChangesEnabled = true;
await db.SaveChangesAsync();

public sealed class DemoDb(DbContextOptions<DemoDb> options) : DbContext(options)
{
    public DbSet<Item> Items => Set<Item>();
}
public sealed class Item
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public List<Child> Children { get; set; } = [];
}
public sealed class Child
{
    public int Id { get; set; }
    public int ItemId { get; set; }
}

AddNewEntitiesFromNavigations selects Modified or Detached tracked roots, reads collection navigation values, checks each child with IsNewEntity and adds the resulting batch.

GetPossibleUpdatingEntities calls DetectChanges and selects Detached/Modified entries. GetNewEntitiesFromNavigations(entry) scans one root; its parameterless form scans those possible roots. GetCollectionNavigations(Type) selects collection, non-shadow INavigation metadata.

⚠️ Gotchas & limits