实体框架5改变日志如何实现?

时间:2014-01-06 01:55:58

标签: asp.net-mvc-4 entity-framework-5

我正在使用MVC4和实体框架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;
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

无需覆盖SaveChanges。

你可以

根据您的代理方法,可能需要触发Context.ChangeTracker.DetectChanges(); //

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

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

示例立即窗口调用。 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]);
        }
    }
}

编辑:获取更改

我使用这个例程来获取chnages ......

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

编辑2如果必须使用内部对象跟踪。

    var context =  ???// YOUR DBCONTEXT class
     // get objectcontext from dbcontext... 
     var   objectContext = ((IObjectContextAdapter) context).ObjectContext;
        // for each tracked entry
        foreach (var dbEntityEntry in context.ChangeTracker.Entries()) {
          //get the state entry from the statemanager per changed object
          var stateEntry =  objectContext.ObjectStateManager.GetObjectStateEntry(dbEntityEntry.Entity);
            var modProps = stateEntry.GetModifiedProperties();
            Debug.WriteLine(modProps.ToString());
        }

我反编译了EF6。获得修改确实是使用私有位数组来跟踪具有的字段 已经改变了。

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