0

How instruct EF to don't delete OneToMany relations but cascade delete collections?

i.e.:

public class Client
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int ClientId { get; set; }
    [ForeignKey("ClientId")]
    public Client Client { get; set; }
    public ICollection<OrderItem> OrderItems { get; set; }
}

public class OrderItem
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    [ForeignKey("OrderId")]
    public Order Order { get; set; }
}

In this model, when I try to delete a Client associated with some Orders I would like to avoid the deletion (1). However when I try to delete a Order with some OrderItems I would like to remove the Order and the associeted OrderItems (2).

I also have one limitation about the FK column: it's in [Model]Id format instead the EF default [Model]_Id form.

If I define

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

the (1) works fine but (2) trigger an error.

There's an alternative except using Fluent for each collection? How do to this in Fluent anyway?

Max Bündchen
  • 1,283
  • 17
  • 38

1 Answers1

2

Both you cases are one-to-many relations. By removing cascade delete convention you tell EF that both cases should be handled without cascade delete.

You need to use fluent API if you want to control cascade delete per relation:

modelBuilder.Entity<Order>()
            .HasMany(o => o.OrderItems)
            .WithRequired(i => i.Order)
            .HasForeignKey(i => i.OrderId)
            .WillCascadeOnDelete(true);

modelBuilder.Entity<OrderItem>()
            .Property(i => i.OrderId)
            .HasColumnName("OrderId");

You can also use the convention (or remove it) and use fluent API only for relations when you want to change the behavior.

If you don't want to have OrderId property you can use:

modelBuilder.Entity<Order>()
            .HasMany(o => o.OrderItems)
            .WithRequired(i => i.Order)
            .Map(m => m.MapKey("OrderId"))
            .WillCascadeOnDelete(true);

Beware that those two options have different implementation in EF.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • In the case of using fluent API the OrderId property is really necessary? Is there a way to 'map' the column "OrderId" to OrderItem.Order nav property? – Max Bündchen Apr 16 '13 at 19:22
  • @Mrnka thank you very much for your help. If I may, I will ask how to use the Map() sintax to avoid the ItemId property in the OrderItem as in that case I don't have a cross association as in Order and OrderItem. – Max Bündchen Apr 16 '13 at 20:56
  • Now I'm not sure what you are asking for. If you mean that you don't have navigation properties on both sides you can still use that syntax because `WithRequired` can be also used without parameter. You still need navigation property at least at one side to define the relation. – Ladislav Mrnka Apr 16 '13 at 20:59