受到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以重新删除新删除的项目。我怎么解决这个问题?还是有其他解决方案吗?或者我做错了吗?
答案 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 }