Mittwoch, 7. Februar 2018

Handling child collectins in EF (now Core) - Again

I hitted the same issue as described in a previous post once again. Last time it was EF6, this time EF Core.

It is about having a simple model with a parent entity having a collection of child entities like in

public class Basket
{
    public Guid Id { get; set; }
    public Guid CustomerId { get; set; }
    public virtual IList<BasketItem> Positions { get; set; }
}

public class BasketItem
{
    public int Id { get; set; }
    public string ArticleName { get; set; }
    public decimal Amount { get; set; }
    public decimal Price { get; set; }
}

public class BasketContext : DbContext
{
    public BasketContext() : base("BasketContext") 
    {
    }
    
    public DbSet<Basket> Baskets { get; set; }
}

Please notice that there are neither unecessary navigation properties nor unecessary DbSets in the context.

With EF6 we needed to override the OnSaveChanges method to handle the problem, but things got better with EF Core. While the default behaviour still is an optional relationship whose foreign key will be set null on the database, we can now configure the relationship to be required and cascade on delete like so:


protected override void OnModelCreating(ModelBuilder modelBuilder)
{
            
     modelBuilder.Entity()
                .HasOne(typeof(Basket))
                .WithMany(nameof(Basket.Positions))
                .IsRequired()
                .OnDelete(DeleteBehavior.Cascade);

     base.OnModelCreating(modelBuilder);
}

Thanks to EF core it is now possible to define one-to-many relationships without the need of an explicit navigation property just by giving it a type. The IsRequired call makes the FK-filed on the database non nullable and the delete behaviour yields to the deletion of the chilg, as described in the EF Core docs on the topic.

So while I still feel that the EF Core default is unatural, the possibilities to fix the error became much cleaner.