使用ChangeTracker的EF Audit Trail - 检测Navigation属性的变化

时间:2017-11-20 05:07:33

标签: c# entity-framework entity-framework-6

我正在尝试通过覆盖SaveChangeAsync方法来实现Audit Trail。使用ChangeTracker.Entries(),我可以获得正在修改或添加的所有属性的列表。这适用于没有任何FK的普通实体。但是对于FK,如果我通过导航属性分配了外国实体,ChangeTracker没有检测到相关FK的变化。

让我说我有这些课程

class Parent{
  int ParentID,
  string Name,
}

class Child {
  int ChildID,
  int GenderID,
  string Name

  virtual Gender Gender{get;set;}
}

class ParentChild {
   int ParentChildID,
   int ParentID,
   int ChildID,
   string RelationName;

  virtual Parent Parent {get;set;}
  virtual Child Child {get;set;}
}

插入新记录

Var p = new Parent{ Name="p1"};
var c = new Child {Name ="c1"};

context.ParentChild.Add(new ParentChild {
  Parent = p,
  Child = c,
  RelationName = "First child"
};

context.SaveChangeAsync();

这里的问题是因为我通过导航属性在ParentChild实体中分配父和子,ChangeTracker没有检测到ParentID&amp ;;的任何变化。 ParentChild实体中的ChildID,但DB确实更新了两个FK。

这就是我记录更改的方式

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            var modifiedEntities = ChangeTracker.Entries()
        .Where(p => p.State != EntityState.Unchanged && p.State != EntityState.Detached).ToList();
            var now = DateTime.UtcNow;
            List<AuditTemp> changes = new List<AuditTemp>();
            foreach (var change in modifiedEntities)
            {
                var entityName = change.Entity.GetType().Name;
                var primaryKey = GetPrimaryKeyValue(change) ?? 0;

                foreach (var prop in change.CurrentValues.PropertyNames)
                {
                    string originalValue = "";
                    string currentValue = "";
                    currentValue = (change.CurrentValues[prop]??"").ToString();
                    if (change.State == EntityState.Modified)
                        originalValue = (change.OriginalValues[prop]??"").ToString();

                    if (originalValue != currentValue)
                    {
                        AuditTemp log = new AuditTemp()
                        {
                            Entity = change,
                            Audit = new Audit()
                            {
                                TableName = entityName,

                                FieldName = prop,
                                OldValue = originalValue,
                                NewValue = currentValue,
                                UpdateDate = now
                            }
                        };
                        changes.Add(log);
                    }
                }

            }
             int a =  await base.SaveChangesAsync(cancellationToken);
            foreach (var c in changes)
            {
                c.Audit.NewValue = c.Entity.CurrentValues[c.Audit.FieldName].ToString();
                c.Audit.RecordID = Convert.ToInt64(GetPrimaryKeyValue(c.Entity)??0);
                this.Audits.Add(c.Audit);
            }

            await base.SaveChangesAsync(cancellationToken);
            return a;
        }

我在调用SaveChanges后更新/添加日志以获取Insert的自动生成密钥。

我可以通过任何方式检测FK中的更改(通过导航属性更新)并记录它们。

非常感谢

0 个答案:

没有答案
相关问题