Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework CTP5, code-first. Many to many with cascade delete

I have two entities (Customer and CustomerRole) and would like to declare many-to-many relationship between them. I can do using the following code:

modelBuilder.Entity<CustomerRole>()
        .HasMany(cr => cr.Customers) 
        .WithMany(c => c.CustomerRoles)
        .Map(m => m.ToTable("Customer_CustomerRole_Mapping"));

But it creates the relationship (and the third mapping table) with cascade delete switched off by default. How can I tell EF to create the relationship with cascade delete switched on when using many-to-many?

like image 555
Andrei M Avatar asked Jan 04 '11 12:01

Andrei M


1 Answers

As of CTP5, there seems to be no way to directly turn on cascade deletes on Many to Many associations by Fluent API.

That said, if your intention is to make sure that you can delete the principal (e.g. a Customer record) without having to worry about the dependent record in the join table (i.e. Customer_CustomerRole_Mapping) then you don't need to turn on cascades on the database since EF Code First will take care of the cascade deletes on the client side when it comes to Many to Many associations.

For example, when you delete a Customer object, EF is smart enough to first send a delete statement to get rid of the dependent record in the join table and after that it will send another delete statement to delete the Customer record.

Update:

Due to a bug in CTP5, you need to explicitly eager/Lazy load the navigation property and have it loaded on the context when you remove the dependent. For example, consider this model:

public class User
{
 public int UserId { get; set; }
 public virtual ICollection Addresses { get; set; }
}

public class Address
{
 public int AddressID { get; set; } 
 public virtual ICollection Users { get; set; }
}

Assuming that we have a User with an address in the database, this code will throw:

using (EntityMappingContext context = new EntityMappingContext())
{
 User user = context.Users.Find(1); 
 context.Users.Remove(user);
 context.SaveChanges();
}

However, this one will perfectly work with removing the link table's record first:

using (EntityMappingContext context = new EntityMappingContext())
{
 User user = context.Users.Find(1); 
((IObjectContextAdapter)context).ObjectContext
                                .LoadProperty(user, u => u.Addresses);
 context.Users.Remove(user);
 context.SaveChanges();
}

Please note that this is just a workaround and we will be able to (hopefully) remove a principal without loading its navigation property.

like image 113
Morteza Manavi Avatar answered Oct 13 '22 19:10

Morteza Manavi