我试图实现使用EF 4.1的审计日志,通过如在以下地方讨论重写的SaveChanges()方法:实体框架的DbContext的SaveChanges()OriginalValue错误
- http://jmdority.wordpress.com/2011/07/20/using-entity-framework-4-1-dbcontext-change-tracking-for-audit-logging/
- Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change
虽然我遇到了“修改”条目的问题。无论何时我试图获取相关财产的原始价值,它始终与其在CurrentValue字段中的值相同。
我第一次使用此代码,并将其成功地识别被修改的条目:
public int SaveChanges(string userID)
{
// Have tried both with and without the following line, and received same results:
// ChangeTracker.DetectChanges();
foreach (
var ent in this.ChangeTracker
.Entries()
.Where(p => p.State == System.Data.EntityState.Added
p.State == System.Data.EntityState.Deleted
p.State == System.Data.EntityState.Modified))
{
// For each change record, get the audit record entries and add them
foreach (AuditLog log in GetAuditRecordsForChange(ent, userID))
{
this.AuditLog.Add(log);
}
}
return base.SaveChanges();
}
的问题是在这(简称代码):
private List<AuditLog> GetAuditRecordsForChange(DbEntityEntry dbEntry, string userID)
{
if (dbEntry.State == System.Data.EntityState.Modified)
{
foreach (string propertyName in dbEntry.OriginalValues.PropertyNames)
{
if (!object.Equals(dbEntry.OriginalValues.GetValue<object>(propertyName),
dbEntry.CurrentValues.GetValue<object>(propertyName)))
{
// It never makes it into this if block, even when
// the property has been updated.
}
// If I updated the property "Name" which was originally "OldName" to the value "NewName" and then break here and inspect the values by calling:
// ?dbEntry.OriginalValues.GetValue<object>("Name").ToString()
// the result will be "NewName" and not "OldName" as expected
}
}
}
奇怪的是,在这种情况下调用dbEntry.Property(propertyName).IsModified();
将 返回true。只是这个OriginalValue里面没有预期的值。任何人都愿意帮助我指出正确的方向吗?我似乎无法让这个工作正常。
你是如何查询你的实体,然后改变属性值?如果你基本上是附加实体,然后将状态设置为修改,那么原始值将会丢失。要保留原始值,您需要让EF一直追踪实体直到保存,否则您需要跟踪自己代码中的原始值。 – 2012-03-06 18:11:27
对不起 - 我试图在评论中发布一些代码,但它运行不正常。我正在使用MVC控制器的[HttpPost]动作。这会调用我的产品存储库的“SaveProduct”方法。在存储库中,它看起来确实调用了'context.Entry(product).State = EntityState.Modified',然后我在上下文中调用SaveChanges。 你能指点我的任何资源来展示你提到的两种技术吗?或者至少给我几个指点? – 2012-03-06 18:25:40
我在MVC中建议使用隐藏字段。基本上你会将你关心的原始值保存到隐藏的字段中,然后在POST中将它们读回来。我不知道这方面的最佳做法,或者是否有MVC抽象帮助。 – 2012-03-06 18:40:32