【问题标题】:Override DbSet.Remove() or Restore Entity values within DbContext ChangeTracker.DetectChanges()覆盖 DbSet.Remove() 或恢复 DbContext ChangeTracker.DetectChanges() 中的实体值
【发布时间】:2018-05-04 17:53:20
【问题描述】:

我目前面临的问题是我正在对所有对象实施软删除,但实体上的.Remove() 将在其处理过程中删除外键。

我的对象(即):

ID = 1

名字 = 废话

PageID = null(在调用 .Remove() 之前为 10,我想在 SoftDelete 期间保留它)

是否可以覆盖public virtual TEntity Remove(TEntity entity)?或修改我的ChangeTracker.DetectChanges(); 部分?

就像我简要提到的,我使用ChangeTracker.DetectChanges(); 将实体 (ObjectStateEntry) 设置回已修改 (entry.ChangeState(EntityState.Modified);) 并将另一个属性 IsActive 设置为 false,但是其他字段的“剥离”有在调用 .Remove() 时已经完成。

MVC 为我的所有对象创建控制器,在 DeleteConfirm 中是 db.entityObject.Remove(entity)

...或者我应该研究其他方法吗?

我可以提供更多详细信息,请让我知道您可能需要什么。

控制器中的示例:

// POST: MyObject/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(Guid id)
{
    MyObject myObject = db.MyObject.Find(id);
    db.MyObject.Remove(myObject);
    db.SaveChanges();
    return RedirectToAction("Index");
}
    

我的DbContext 代码的子集:

public class AppDbContext : DbContext
{
    public override int SaveChanges()
    {
        ChangeTracker.DetectChanges();
        
        objectContext.ObjectStateManager.GetObjectStateEntries(
            EntityState.Added | 
            EntityState.Modified | 
            EntityState.Deleted);

        foreach (ObjectStateEntry entry in objectStateEntryList)
        {
            if (!entry.IsRelationship)
            {
                switch (entry.State)
                {
                    case EntityState.Deleted:
                        entry.ChangeState(EntityState.Modified);
                        ((BaseObject)entry.Entity).IsActive = false;
                        

                        //Update #1
                        this.Entry(entry.Entity).Reload();
                        
                        
                        //Is is possible to "restore" the original object?
                        //or override .Remove()?
                        
                        break;
                }
            }
        }
        
        return base.SaveChanges();
    }
}

提前谢谢你。

更新 1:

是不是就这么简单的调用如下?

this.Entry(entry.Entity).Reload();

我认为这有效,我知道这可能是另一个数据库调用,但现在可以解决。需要进一步测试。

【问题讨论】:

  • 为什么不直接更新IsActive 属性?我知道这种软删除方法经常被提倡,even by the EF team themselves,但我一直在想:如果最终它更新,为什么不直接更新呢?另一个原因是级联 hard 删除与其对应的 soft 有根本的不同。
  • 我想继续使用脚手架创建的context.MyObject.Remove(myObject)。另外,虽然我没有提到它,但在ChangeTracker.DetectChanges(); 之后,我已经为对象和所有属性实现了自己的审核日志,向审核日志发送“SoftDelete”可以将所有内容保持在一起。
  • 一天多的时间都在寻找一丝曙光,终于看到了一线希望……感谢@Derek 的“更新 1”。

标签: c# entity-framework dbcontext


【解决方案1】:

让我建议@Derek:

更新 2:

public class AppDbContext : DbContext
{
    public override int SaveChanges()
    {
        ChangeTracker.DetectChanges();
        
        objectContext.ObjectStateManager.GetObjectStateEntries(
            EntityState.Added | 
            EntityState.Modified | 
            EntityState.Deleted);

        foreach (ObjectStateEntry entry in objectStateEntryList)
        {
            if (!entry.IsRelationship)
            {
                switch (entry.State)
                {
                    case EntityState.Deleted:
                        // Update #2
                        // ---------
                        // Set the state to 'Unchanged'.
                        // Only updated fields will be sent to the Db.
                        entry.ChangeState(EntityState.Unchanged);
                        ((BaseObject)entry.Entity).IsActive = false;
                        break;
                }
            }
        }
        
        return base.SaveChanges();
    }
}

感谢 Ryan Southgate 的 Entity Framework Core: Soft Delete 博文。

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 2021-03-22
    相关资源
    最近更新 更多