如何在实体框架中添加删除回调?

时间:2016-05-04 16:10:17

标签: entity-framework

受到rails上的ruby的启发,我想在实体框架中添加一个删除回调。我首先重写了SaveChanges()以遍历被跟踪的实体,并创建一个在实体被删除时调用的接口。

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);
    }
}

这很有效,但我想到了一个问题,我不知道如何解决这个问题。如果实体在 回调中被删除,则需要更新Changetracker以重新删除新删除的项目。我怎么解决这个问题?还是有其他解决方案吗?或者我做错了吗?

2 个答案:

答案 0 :(得分:1)

好问题。如果我理解正确,您的BeforeDelete实现可能会删除另一个需要BeforeDelete调用的条目。这可以递归地进行,所以我唯一能想到的就是递归检查更改跟踪器条目,看看在最后一批处理完成后是否添加了新的跟踪器。

未测试:

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();
}

答案 1 :(得分:0)

您可以过滤掉未经修改的实体更改...

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

并锁定“if”块中的其余部分

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