c# - 我应该如何覆盖 DbContext 上的 SaveChanges() 方法,以便使用 EF 4.3 维护已删除/修改的记录?

标签 c# entity-framework

我想在我的项目中维护所有修改的记录和删除的记录,并使用状态列跟踪它们的状态。下面是我第一次尝试的代码,但由于显而易见的原因,我似乎无法将 OriginalValues.ToObject() 转换为 DbEntityEntry。我应该如何着手完成这项工作?

    public override int SaveChanges()
    {
        var now = DateTime.Now;
        var currentUser = HttpContext.Current.User.Identity.Name;
        var trackedEntities = ChangeTracker.Entries<ITrackable>();

        foreach (var trackedEntity in trackedEntities)
        {
            switch(trackedEntity.State)
            {
                case System.Data.EntityState.Added:
                    trackedEntity.Entity.CreatedDate = now;                        
                    trackedEntity.Entity.CreatedBy = currentUser;                        
                    trackedEntity.Entity.Status = Status.Active;
                    break;
                case System.Data.EntityState.Modified:                        
                    var originalEntity = trackedEntity.OriginalValues.ToObject() as DbEntityEntry<ITrackable>;                        
                    originalEntity.Entity.ModifiedDate = now;
                    originalEntity.Entity.ModifiedBy = currentUser;
                    originalEntity.Entity.Status = Status.Modified;

                    var newEntity = trackedEntity.CurrentValues.ToObject() as DbEntityEntry<ITrackable>;
                    newEntity.State = System.Data.EntityState.Added;
                    newEntity.Entity.Status = Status.Active;                                                
                    break;
                case System.Data.EntityState.Deleted:
                    trackedEntity.State = System.Data.EntityState.Modified;
                    trackedEntity.Entity.Status = Status.Deleted;
                    break;                            
            }                
        }
        return base.SaveChanges();
    }

最佳答案

我不确定我是否正确理解了您在 Modified 中想要实现的目标案件。但我的理解是 ToObject()创建一个全新的对象并用 OriginalValues 中的属性值填充它字典。所以,originalEntity不附加到上下文,当变量超出范围时将被垃圾收集而不会产生任何影响。

因此,您不需要保存 originalEntity 吗?作为一个新添加的实体到数据库来保存修改保存前的最后一个版本?

我会试试这个:

case System.Data.EntityState.Modified:                        
    var originalEntity = trackedEntity.OriginalValues.ToObject() as ITrackable;
    originalEntity.ModifiedDate = now;
    originalEntity.ModifiedBy = currentUser;
    originalEntity.Status = Status.Modified;
    Entry(originalEntity).Status = System.Data.EntityState.Added;

    trackedEntity.Entity.Status = Status.Active;
    break;

trackedEntity无论如何都会被保存,因为它处于状态 ModifiedoriginalEntity将被创建并保存为一个新对象,代表修改前的状态。

我希望转换为 ITrackable应该可以,因为 ToObject()创建一个由 OriginalValues 表示的类型的对象字典,那必须是 ITrackable因为你过滤了 ChangeTracker.Entries通过此接口(interface)进行枚举。

以上内容未经测试,我不确定它是否有效。

编辑

上面的命名有点困惑,因为originalEntity是您模型中的一个实体,而 trackedEntityDbEntityEntry<T> .也许将其重命名为 originalEntityObject (丑)或更好trackedEntityEntry .

只需提及:调用 ChangeTracker.DetectChanges() 是绝对必要的(除非您因此使用更改跟踪代理)在您输入 foreach 之前循环,否则条目可能不处于正确的最终状态并且您输入错误 case部分或根本没有部分(当状态为 Unchanged 但属性仍已更改时)。通过与 OriginalValues 中的快照进行比较来检测 POCO 更改最后的比较是在 base.SaveChanges 中完成的这是你的循环之后,为时已晚。 (另请参阅此处答案中的“编辑 2”:https://stackoverflow.com/a/6157071/270591。)

关于c# - 我应该如何覆盖 DbContext 上的 SaveChanges() 方法,以便使用 EF 4.3 维护已删除/修改的记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10502325/

相关文章:

c# - Windows 窗体/ TreeView : How do I put CheckBoxes only on the leaves?

unit-testing - 是否可以 stub Entity Framework 上下文和类来测试数据访问层?

c# - 如何在 MVC 中定义 @Html.DisplayFor 的最大长度?

c# - 分配给委托(delegate)的通用方法

c# - 降低单点触控中 native <-> 托管交互的成本

c# - 在 JSON post 请求中提供 AntiForgeryToken

c# - Entity Framework 中的一对多关系导致异常

c# - .NET 核心 2.1 和 EF 框架 2.1

.net - 使用 Entity Framework 使用 SQL Azure 进行 transient 故障处理

c# - WinForms 主窗口句柄