【发布时间】:2012-03-24 04:56:43
【问题描述】:
我正在尝试使用 EF 4.1 实现 AuditLog,方法是覆盖以下位置讨论的 SaveChanges() 方法:
- 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
我在“修改”条目方面遇到了问题。每当我尝试获取相关属性的 OriginalValue 时,它始终具有与 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 从查询到保存一直跟踪实体,或者您需要在自己的代码中跟踪原始值。
-
抱歉 - 我试图在 cmets 中发布一些代码,但效果不佳。我正在使用 MVC 控制器的 [HttpPost] 操作。这调用了我的产品存储库的“SaveProduct”方法。在存储库中,看起来我确实调用了
context.Entry(product).State = EntityState.Modified,然后我在上下文中保存了更改。您能否向我指出演示您提到的两种技术的任何资源?或者至少给我一些指点? -
我认为在 MVC 中推荐的方法是使用隐藏字段。本质上,您会将您关心的原始值保存到隐藏字段中,然后稍后在您的 POST 中读回它们。我不知道这方面的最佳实践,或者是否有 MVC 抽象来提供帮助。
-
特别是,我想知道如何“让 EF 从查询到保存一直跟踪实体”。我认为这已经发生了。当我进一步调查时,我发现在存储库中,就在我调用 context.Entry(product).State = EntityState.Modified 之前,我可以看到原始值(“OldValue”)。但是,只要我调用那行代码,DBContext 中感兴趣的“产品”就会将其
OriginalValue和CurrentValue设置为“NewValue”。所以,我看你是对的,但我不知道如何以 EF 将跟踪的方式更新它。 -
在我最近发表评论之前,我没有看到您的第二篇文章。我真的很感谢你在这方面的帮助。你认为我现在应该创建另一个关于在 MVC 中执行此操作的首选方式的 SO 问题吗?
标签: c# entity-framework entity-framework-4.1 ef-code-first