Reputation: 433
If I have a relationship like this in a .NET MVC project using entity framework (dbsets in a database context with models etc.).
class A {
contains a list of class C objects (one-to-many)
}
class B {
contains a list of class C objects (one-to-many), often many of the
same class C entries which class A uses aswell
}
class C {
contains class D elements
}
class D { }
So the main problem is that class A is a model I want to delete often as the data in it is only supposed to exist for a fixed amount of time (then it is deleted by a cron job), but for some reason when I remove class A entries it seems to mess with the relation between class C and class D, removing class D items from my class C entries in the database.
Is there some way I can delete entries in my class A database table, while making sure that it leaves ALL the other tables alone completely and without exception?
I've read on disabling cascade delete, but to be honest I'm confused on how I'm supposed to understand what weird relation that's into play in this particular context and I'm not quite sure what I should be disabling it on.
I hope this example makes sense I've tried to explain it as simply as possible.
Upvotes: 0
Views: 1091
Reputation: 759
By default EF has a OneToManyCascadeDeleteConvention
enabled. This works like by setting a SQL cascade delete on the foreign key between the tables. When the primary object is deleted, any objects that are foreign keyed to that object will also be deleted. Thus, in your example, when you delete A
it will also delete all C
objects that are in the collection. And because we cascade it will also delete all of the D
objects (assuming you mean that C
contained a one-to-many collection of D
objects) that are in all those C
object's collections.
The OneToManyCascadeDeleteConvention
, however, only applies if the foreign key field is set to being required. Setting it to nullable (as in the example below) should disable the convention.
public class ObjectA
{
public int ObjectAId { get; set; }
public virtual ICollection<ObjectC> ObjectCCollection { get; set; }
}
public class ObjectC
{
public int? ObjectAId { get; set; }
public virtual ObjectA ObjectA { get; set; }
}
That being said, you can also selectively remove the cascade between ObjectA
to ObjectC
during entity configuration using an EntityTypeConfiguration
.
internal class ObjectCMap : EntityTypeConfiguration<ObjectC>
{
public ObjectCMap()
{
this.HasOptional(o => o.ObjectA).WithMany(o => o.ObjectCCollection).WillCascadeOnDelete(false);
}
}
and then register it with the model builder in the DbContext
modelBuilder.Configurations.Add(new ObjectCMap());
If the foreign key field on ObjectC
isn't nullable, however, SQL will throw a foreign key error when you try to delete ObjectA
.
Upvotes: 1