我试图通过覆盖SaveChanges()方法使用EF 4.1实现AuditLog,如下所述:
我遇到了"修改"条目的问题.每当我尝试获取相关属性的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();
}
Run Code Online (Sandbox Code Playgroud)
问题在于此(缩写代码):
private List<AuditLog> …Run Code Online (Sandbox Code Playgroud) 我正在编写一个来自网上代码片段的审计线索.在调用我的SaveChanges函数时,我遍历所有使用Context注册的已修改实体,并根据其更改构建日志条目.
foreach (DbEntityEntry modifiedEntity 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 changed record, get the audit record entries and add them
foreach(AuditLog x in GetAuditRecordsForChange(modifiedEntity, userId))
{
this.AuditLog.Add(x);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当我尝试访问修改后的实体的原始值时,将填充所有标量属性,但复杂的属性不存在(属性计数将为6而不是8).然后我调用ToObject()以原始状态构建对象,但显然复杂属性都是空值.
modifiedEntity.OriginalValues.ToObject()
Run Code Online (Sandbox Code Playgroud)
这只发生在我的一些域对象中,并且这些对象在ToObject()调用之后总是显示为代理,而(我不确定为什么)但没有实体为它们创建代理的那些,它们的复杂属性填充得很好.当我在我的应用程序中正常使用POCO代理时,延迟加载可以正常工作.
我注意到如果我对其中一个未作为OriginalValues数据的一部分填充的复杂属性进行更改,则对象的状态不会更改为Modified,这是有意义的,因为更改跟踪将原始值与当前值进行比较看它是否改变了.什么没有什么意义的是,该数据仍然坚持在SaveChanged?
编辑:我刚刚注意到,模型对象确实填充了它的复杂属性,所讨论的复杂属性(按惯例)被实体视为"复杂类型",即没有主键.
有任何想法吗?
我尝试了很多不同的方法并查看了不同的帖子,但仍未找到这种审核方式的解决方案.下面是我的DBContext模板文件.我通过添加OnContextCreated()partial方法来定制它,并将SavingChanges事件分配给我的OnSavingChanges事件处理程序.
namespace ARSystem.Models
{
public partial class ARSEntities : ObjectContext
{
public ARSEntities()
: base("name=ARSEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public string UserName { get; set; }
List<DBAudit> auditTrailList = new List<DBAudit>();
public enum AuditActions
{
I,
U,
D
}
partial void OnContextCreated()
{
this.SavingChanges += new EventHandler(OnSavingChanges);
}
public void OnSavingChanges(object sender, EventArgs e)
{
IEnumerable<ObjectStateEntry> changes = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);
foreach (ObjectStateEntry stateEntryEntity …Run Code Online (Sandbox Code Playgroud)