Asp.net mvc 4 实体框架5变更日志如何实现?

Asp.net mvc 4 实体框架5变更日志如何实现?,asp.net-mvc-4,entity-framework-5,Asp.net Mvc 4,Entity Framework 5,我正在使用MVC4和entity framework 5创建一个应用程序。我如何实现这一点? 我环顾四周,发现我需要覆盖SaveChanges 有人对此有任何示例代码吗?我使用代码优先的方法 例如,我保存数据的方式如下: public class AuditZoneRepository : IAuditZoneRepository { private AISDbContext context = new AISDbContext(); public

我正在使用MVC4和entity framework 5创建一个应用程序。我如何实现这一点? 我环顾四周,发现我需要覆盖SaveChanges

有人对此有任何示例代码吗?我使用代码优先的方法

例如,我保存数据的方式如下:

 public class AuditZoneRepository : IAuditZoneRepository
    {
        private AISDbContext context = new AISDbContext();



        public int Save(AuditZone model, ModelStateDictionary modelState)
        {
            if (model.Id == 0)
            {
                context.AuditZones.Add(model);
            }
            else
            {
                var recordToUpdate = context.AuditZones.FirstOrDefault(x => x.Id == model.Id);
                if (recordToUpdate != null)
                {
                    recordToUpdate.Description = model.Description;
                    recordToUpdate.Valid = model.Valid;
                    recordToUpdate.ModifiedDate = DateTime.Now;
                }
            }

            try
            {
                context.SaveChanges();
                return 1;
            }
            catch (Exception ex)
            {
                modelState.AddModelError("", "Database error has occured.  Please try again later");
                return -1;
            }
        }
    }

无需覆盖SaveChanges

你可以

触发器
Context.ChangeTracker.DetectChanges()//可能是必需的,具体取决于您的代理方法

然后在保存之前分析上下文。 然后你可以。。。将更改日志添加到当前工作单元。 因此,日志保存在一个提交事务中。 或者按照您认为合适的方式进行处理。 但同时保存更改日志。确保它是一个事务

分析上下文示例: 我有一个简单的工具,可以将上下文内容转储到调试输出,以便在调试器中时可以使用即时窗口检查内容。如 您可以将其用作准备更改日志的启动程序。 在调试器即时窗口中尝试。我的上下文类已完全转储

即时窗口调用示例<代码>UoW.Context.FullDump()

public void FullDump() {

        Debug.WriteLine("=====Begin of Context Dump=======");
        var dbsetList = this.ChangeTracker.Entries();
        foreach (var dbEntityEntry in dbsetList)
        {

            Debug.WriteLine(dbEntityEntry.Entity.GetType().Name + " => " + dbEntityEntry.State);
            switch (dbEntityEntry.State)
            {
                case EntityState.Detached:
                case EntityState.Unchanged:
                case EntityState.Added:
                case EntityState.Modified:
                    WriteCurrentValues(dbEntityEntry);
                    break;
                case EntityState.Deleted:
                    WriteOriginalValues(dbEntityEntry);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            Debug.WriteLine("==========End of Entity======");
        }
        Debug.WriteLine("==========End of Context======");
    }

    private static void WriteCurrentValues(DbEntityEntry dbEntityEntry)
    {
        foreach (var cv in dbEntityEntry.CurrentValues.PropertyNames)
        {
            Debug.WriteLine(cv + "=" + dbEntityEntry.CurrentValues[cv]);
        }
    }
    private static void WriteOriginalValues(DbEntityEntry dbEntityEntry)
    {
        foreach (var cv in dbEntityEntry.OriginalValues.PropertyNames)
        {
            Debug.WriteLine(cv + "=" + dbEntityEntry.OriginalValues[cv]);
        }
    }
}
编辑:获取更改

我用这个程序来获取技术

public class ObjectPair {
    public string Key { get; set; }
    public object Original { get; set; }
    public object Current { get; set; }
 }

public virtual IList<ObjectPair> GetChanges(object poco) {
        var changes = new List<ObjectPair>();
        var thePoco = (TPoco) poco;


        foreach (var propName in Entry(thePoco).CurrentValues.PropertyNames) {
            var curr = Entry(thePoco).CurrentValues[propName];
            var orig = Entry(thePoco).OriginalValues[propName];
            if (curr != null && orig != null) {
                if (curr.Equals(orig)) {
                    continue;
                }
            }
            if (curr == null && orig == null) {
                continue;
            }
            var aChangePair = new ObjectPair {Key = propName, Current = curr, Original = orig};
            changes.Add(aChangePair);
        }
        return changes;
    }
我反编译了EF6。Get modified确实在使用私有位数组来跟踪具有 已经改变了

 // EF decompiled source..... _modifiedFields is a bitarray
 public override IEnumerable<string> GetModifiedProperties()
{
  this.ValidateState();
  if (EntityState.Modified == this.State && this._modifiedFields != null)
  {
    for (int i = 0; i < this._modifiedFields.Length; ++i)
    {
      if (this._modifiedFields[i])
        yield return this.GetCLayerName(i, this._cacheTypeMetadata);
    }
  }
}
//EF反编译源…..\u modifiedFields是位数组
公共重写IEnumerable GetModifiedProperties()
{
这个;
if(EntityState.Modified==this.State&&this.\u modifiedFields!=null)
{
对于(int i=0;i
Phil-这是一个很好的示例。谢谢。我已经更新了上面的代码,我没有使用工作单元。所以你是说在我保存之前,我应该使用更改跟踪器来比较这两组值?如果我有不同的存储库,我是否需要复制代码?有许多存储库是可以的。代码是针对上下文的,所以我可以考虑上下文。考虑工作单位的方法,在其中控制保存,是控制更改日志的地方。UOW模式的存在是为了避免在存储库中保存500种方法;- PHIL -有一种简单的方法来只识别修改后的值吗?在记录中,我可能只改变1字段。current value函数只显示一个已修改的项,还是显示该记录的所有字段?Phil-这听起来可能很傻,但当EF将要更新的数据传递到基础表时,它肯定只向已更改的值发送update语句是吗?即在10个字段的行中,如果只更新了1个字段,则t发送到表中的sql应仅用于更新1个字段?如果是这种情况,那么ChangeTracker是否只会给我更改的数据?因为我只想记录这些…正确的EF更新集。让我看看是否可以快速访问
 // EF decompiled source..... _modifiedFields is a bitarray
 public override IEnumerable<string> GetModifiedProperties()
{
  this.ValidateState();
  if (EntityState.Modified == this.State && this._modifiedFields != null)
  {
    for (int i = 0; i < this._modifiedFields.Length; ++i)
    {
      if (this._modifiedFields[i])
        yield return this.GetCLayerName(i, this._cacheTypeMetadata);
    }
  }
}