1

Inspired by ruby on rails I want to add a delete callback to entity framework. I've started by overriding SaveChanges() to loop over the tracked entities and create an interface which is called whenever an entity gets deleted.

var changedEntities = ChangeTracker.Entries();
foreach (var changedEntity in changedEntities)
{
    if (changedEntity.Entity is IBeforeDelete && changedEntity.State == EntityState.Deleted)
    {
        IBeforeDelete saveChange = (IBeforeDelete)changedEntity.Entity;
        saveChange.BeforeDelete(this, changedEntity);
    }
}

This works quite well, but I figured one problem and I don't know how to solve that. If an entity gets deleted within the callback, the Changetracker needs to be updated to resprect the newly deleted items. How can I solve that? Or is there another solution? Or do I do it wrong?

1
  • Or do I do it wrong? That depends on what you do in saveChange.BeforeDelete. Commented May 4, 2016 at 23:01

2 Answers 2

1

Good question. If I understand you correctly, your BeforeDelete implementations might delete a different entry that also needs to have BeforeDelete called on it. This could recursively go forever, so the only thing I could think of would be to recursively check the change tracker entries to see if new ones were added after the last batch was processed.

Untested:

public override int SaveChanges()
{
    var processed = new List<DbEntityEntry>();
    var entries = ChangeTracker.Entries();

    do
    {
        foreach (var entry in entries)
        {
            processed.Add(entry);

            if (entry.Entity is IBeforeDelete && entry.State == EntityState.Deleted)
            {
                IBeforeDelete saveChange = (IBeforeDelete)entry.Entity;
                saveChange.BeforeDelete(this, entry);
            }
        }
    } while ((entries = ChangeTracker.Entries().Except(processed)).Any());

    return base.SaveChanges();
}
Sign up to request clarification or add additional context in comments.

Comments

0

you can filter out uncommited entity changes...

var changedEntities = Context.ChangeTracker
    .Entries<TEntity>()
    .Where(e => e.State != EntityState.Detached)
    .Select(e => e.Entity);

and lock on the rest in your "if" block

lock(changedEntity.Entity){ ... interface code }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.