Entity framework override save changes to soft delete entities

c# entity-framework entity-framework-6

Question

I am trying to override Savechanges in My Database Context to mark my entites as SoftDeleted.

I have an ISoftDeletable base which i override in my Entity classes

public interface IsoftDeletable
{
    public bool IsDeleted {get; set;}
}

And then in my Context

public override int SaveChanges()
{
    foreach (var entry in ChangeTracker.Entries()
              .Where(p => p.State == EntityState.Deleted))
        SoftDelete(entry);

    return base.SaveChanges();
}

private void SoftDelete(DbEntityEntry entry)
{
   var entity = entry.Entity as ISoftDeltable;
   entity.IsDeleted = true;
   entry.State = EntityState.Modified;
}

The above example works ok if i delete an Entity it gets soft deleted but the problem is that if that entity has Child Collections with Cascade delete, the child collections are not tracked by the Entity Framework and they are not marked as deleted.

One simple solution was to eagerly load all of the child Collections of the Entity that is going to be deleted before the delete happens so the Ef tracks the changes in the children too and soft delete them but this is a "hack" i want to avoid. It will be hard to remember all the relations between entities and eager load everything just before the delete happens. Also it will be hard to maintain this if the model changes.

Is there any better way to achieve that funcionallity?

Edit 1: I dont see how this question might be dublicate of this

1
2
5/23/2017 11:46:26 AM

Popular Answer

I would try something on the DBMS side, not on the application side.

I'm gonna assume that you have MS SQL Server. MS SQL Server supports "on cascade update" in a similar fashion as "on cascade delete". It means that if you have an Person table with primary key PersonID and a Car table where there is a PersonID foreign key referencing the PersonID in the Person table, whenever you change the value in Person for PersonID, the foreign key in the related record in Car is also updated with this value.

So in your case what I would do is modify the foreign keys. Let's say you have two tables:

Person: (PersonId, Name, Age, IsDeleted)
Car: (CarId, Make, Model, PersonId, IsDeleted)

PersonID is the PK in Person, and CarId is the PK in Car. And instead of making Car.PersonId a FK referencing Person.PersonId, you create a composite foreign key: (Car.PersonId, Car.IsDeleted) => (Person.PersonId, Person.IsDeleted) AND you specify the "on update cascade" option for this composite FK. This way whenever you change Person.PersonId (which you never will) or Person.IsDeleted, the new values will be cascade updated into the corresponding Car.PersonId (which again, will not be cascade updated because Person.PersonId will not change) and Car.IsDeleted.

2
3/8/2017 9:07:27 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow