将 SaveChange 中的旧值和新值保存为 DbEntityEntry.Entity 以进行审核
Hold Old and New value in SaveChange as DbEntityEntry.Entity to Audit
如您所知,我们可以在 SaveChange()
中审核对象,但我对已修改和已删除的实体存在一些问题,如下所示,
首先,我使用 Audit.Net(这使用起来非常简单)来审核我的对象,下面的方法应该进行审核:
private int SaveAuditRecord(DbEntityEntry dbEntry, string userGUID)
{
Logging.Log(LoggingMode.Error, "Saving Audid Entry{0}....", dbEntry.ToString());
DateTime changeTime = DateTime.UtcNow;
TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), true).SingleOrDefault() as TableAttribute;
string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;
Logging.Log(LoggingMode.Error, "TableName Retrived {0}...", tableName);
switch (dbEntry.State)
{
case System.Data.Entity.EntityState.Added:
int result = base.SaveChanges();
AuditNet.AuditMonoAction("Add " + tableName, userGUID, dbEntry.Entity);
return result;
case System.Data.Entity.EntityState.Deleted:
AuditNet.AuditMonoAction("Delete " + tableName, userGUID, dbEntry.Entity);
break;
case System.Data.Entity.EntityState.Modified:
int modifiedResult = 0;
var primaryKey = GetPrimaryKeyValue(dbEntry);
modifiedResult = base.SaveChanges();
object entity2Audit = dbEntry.Entity;//Hold the current entity here and change it in below Audit using block
using (var audit = Audit.Core.AuditScope.Create("Edit " + tableName, () => dbEntry.Entity))
{
audit.SetCustomField("UserGUID", userGUID, false);
foreach (var prop in dbEntry.OriginalValues.PropertyNames)
{
var originalValue = dbEntry.OriginalValues[prop].ToString();
var currentValue = dbEntry.CurrentValues[prop].ToString();
if (originalValue != currentValue)
Logging.Log(LoggingMode.Error, "Prop {0} get originalValue :{1} , currentValue:{2}", prop, originalValue, currentValue);
}
}
return modifiedResult;
default:
break;
}
return base.SaveChanges();
}
1- 对于添加状态,没有问题,因为我正在审核 dbEntry.Entity
,我认为它始终包含当前值。
2- 对于 Delete
和 Modify
有一些问题,
删除:我认为我正在审核 dbEntry.Entity
,它正在寻找当前值并引发异常:
CurrentValues cannot be used for entities in the Deleted state.
修改:总是OldValue
和NewValue
总是和我上面提到的CurrentValue
一样
所以我的主要问题是如何像 dbEntry.Entity
那样进行删除和修改?
P.S:
在 Using 块中,我们可以更改审计对象以将 NewValue 设置为 Audit.Net 提到的。
更新1:
即使使用此代码,旧值和新值始终相同:
int modRes = 0;
object entity2Audit = dbEntry.Entity;//Hold the current entity here and change it in below Audit using block
DbEntityEntry dbEntryTemp = dbEntry;
foreach (var prop in dbEntryTemp.OriginalValues.PropertyNames)
{
var originalValue = dbEntry.OriginalValues[prop].ToString();
var currentValue = dbEntry.CurrentValues[prop].ToString();
if (originalValue != currentValue)
{
Logging.Log(LoggingMode.Error, "Prop11 {0} get originalValue :{1} , currentValue:{2}", prop, originalValue, currentValue);
dbEntryTemp.CurrentValues[prop] = dbEntryTemp.OriginalValues[prop] = originalValue;
}
}
object en = dbEntryTemp.Entity;
using (var audit = Audit.Core.AuditScope.Create("Edit " + tableName, () => en))
{
modRes = base.SaveChanges();
audit.SetCustomField("UserGUID", userGUID, false);
audit.SetCustomField("NewValue", dbEntry.Entity, false);
audit.SetCustomField("OldValue", en, false);
en = dbEntry.Entity;
}
首先我要感谢 thepirat000 制作了 Audit.Net 库,这是一个非常好的审计库,有很多选项,正如他在 GitHub
中提到的
但是关于我的问题,这是我第一次覆盖 SaveChange()
并且我也不知道 DbEntityEntry
对象,但是解决方案看起来很有趣,只需要转换 CurrentValues
和 OriginalValues
到 Object()
,在修改的情况下,我通过 dbEntry.OriginalValues.ToObject()
获取旧值并在 Audit.Net 范围内用 dbEntry.CurrentValues.ToObject()
更改它,即全部。
Logging.Log(LoggingMode.Prompt, "Saving Audid Entry{0}....", dbEntry.ToString());
TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), true).SingleOrDefault() as TableAttribute;
string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;
Logging.Log(LoggingMode.Prompt, "TableName Retrived {0}...", tableName);
switch (dbEntry.State)
{
case System.Data.Entity.EntityState.Added:
int result = base.SaveChanges();
object addedObj = dbEntry.Entity;
using (var audit = Audit.Core.AuditScope.Create("Add " + tableName, () =>addedObj ))
{
audit.SetCustomField("UserGUID", userGUID);
addedObj = null;
}
return result;
case System.Data.Entity.EntityState.Deleted:
object deletedObj = dbEntry.Entity;
using (var audit = Audit.Core.AuditScope.Create("Delete " + tableName, () => deletedObj))
{
audit.SetCustomField("UserGUID", userGUID);
deletedObj = null;
}
break;
case System.Data.Entity.EntityState.Modified:
object en = dbEntry.OriginalValues.ToObject();
using (var audit = Audit.Core.AuditScope.Create("Edit " + tableName, () => en))
{
audit.SetCustomField("UserGUID", userGUID);
en = dbEntry.CurrentValues.ToObject();
}
break;
default:
break;
}
return base.SaveChanges();
如您所知,我们可以在 SaveChange()
中审核对象,但我对已修改和已删除的实体存在一些问题,如下所示,
首先,我使用 Audit.Net(这使用起来非常简单)来审核我的对象,下面的方法应该进行审核:
private int SaveAuditRecord(DbEntityEntry dbEntry, string userGUID)
{
Logging.Log(LoggingMode.Error, "Saving Audid Entry{0}....", dbEntry.ToString());
DateTime changeTime = DateTime.UtcNow;
TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), true).SingleOrDefault() as TableAttribute;
string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;
Logging.Log(LoggingMode.Error, "TableName Retrived {0}...", tableName);
switch (dbEntry.State)
{
case System.Data.Entity.EntityState.Added:
int result = base.SaveChanges();
AuditNet.AuditMonoAction("Add " + tableName, userGUID, dbEntry.Entity);
return result;
case System.Data.Entity.EntityState.Deleted:
AuditNet.AuditMonoAction("Delete " + tableName, userGUID, dbEntry.Entity);
break;
case System.Data.Entity.EntityState.Modified:
int modifiedResult = 0;
var primaryKey = GetPrimaryKeyValue(dbEntry);
modifiedResult = base.SaveChanges();
object entity2Audit = dbEntry.Entity;//Hold the current entity here and change it in below Audit using block
using (var audit = Audit.Core.AuditScope.Create("Edit " + tableName, () => dbEntry.Entity))
{
audit.SetCustomField("UserGUID", userGUID, false);
foreach (var prop in dbEntry.OriginalValues.PropertyNames)
{
var originalValue = dbEntry.OriginalValues[prop].ToString();
var currentValue = dbEntry.CurrentValues[prop].ToString();
if (originalValue != currentValue)
Logging.Log(LoggingMode.Error, "Prop {0} get originalValue :{1} , currentValue:{2}", prop, originalValue, currentValue);
}
}
return modifiedResult;
default:
break;
}
return base.SaveChanges();
}
1- 对于添加状态,没有问题,因为我正在审核 dbEntry.Entity
,我认为它始终包含当前值。
2- 对于 Delete
和 Modify
有一些问题,
删除:我认为我正在审核 dbEntry.Entity
,它正在寻找当前值并引发异常:
CurrentValues cannot be used for entities in the Deleted state.
修改:总是OldValue
和NewValue
总是和我上面提到的CurrentValue
一样
所以我的主要问题是如何像 dbEntry.Entity
那样进行删除和修改?
P.S: 在 Using 块中,我们可以更改审计对象以将 NewValue 设置为 Audit.Net 提到的。
更新1:
即使使用此代码,旧值和新值始终相同:
int modRes = 0;
object entity2Audit = dbEntry.Entity;//Hold the current entity here and change it in below Audit using block
DbEntityEntry dbEntryTemp = dbEntry;
foreach (var prop in dbEntryTemp.OriginalValues.PropertyNames)
{
var originalValue = dbEntry.OriginalValues[prop].ToString();
var currentValue = dbEntry.CurrentValues[prop].ToString();
if (originalValue != currentValue)
{
Logging.Log(LoggingMode.Error, "Prop11 {0} get originalValue :{1} , currentValue:{2}", prop, originalValue, currentValue);
dbEntryTemp.CurrentValues[prop] = dbEntryTemp.OriginalValues[prop] = originalValue;
}
}
object en = dbEntryTemp.Entity;
using (var audit = Audit.Core.AuditScope.Create("Edit " + tableName, () => en))
{
modRes = base.SaveChanges();
audit.SetCustomField("UserGUID", userGUID, false);
audit.SetCustomField("NewValue", dbEntry.Entity, false);
audit.SetCustomField("OldValue", en, false);
en = dbEntry.Entity;
}
首先我要感谢 thepirat000 制作了 Audit.Net 库,这是一个非常好的审计库,有很多选项,正如他在 GitHub
中提到的但是关于我的问题,这是我第一次覆盖 SaveChange()
并且我也不知道 DbEntityEntry
对象,但是解决方案看起来很有趣,只需要转换 CurrentValues
和 OriginalValues
到 Object()
,在修改的情况下,我通过 dbEntry.OriginalValues.ToObject()
获取旧值并在 Audit.Net 范围内用 dbEntry.CurrentValues.ToObject()
更改它,即全部。
Logging.Log(LoggingMode.Prompt, "Saving Audid Entry{0}....", dbEntry.ToString());
TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), true).SingleOrDefault() as TableAttribute;
string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;
Logging.Log(LoggingMode.Prompt, "TableName Retrived {0}...", tableName);
switch (dbEntry.State)
{
case System.Data.Entity.EntityState.Added:
int result = base.SaveChanges();
object addedObj = dbEntry.Entity;
using (var audit = Audit.Core.AuditScope.Create("Add " + tableName, () =>addedObj ))
{
audit.SetCustomField("UserGUID", userGUID);
addedObj = null;
}
return result;
case System.Data.Entity.EntityState.Deleted:
object deletedObj = dbEntry.Entity;
using (var audit = Audit.Core.AuditScope.Create("Delete " + tableName, () => deletedObj))
{
audit.SetCustomField("UserGUID", userGUID);
deletedObj = null;
}
break;
case System.Data.Entity.EntityState.Modified:
object en = dbEntry.OriginalValues.ToObject();
using (var audit = Audit.Core.AuditScope.Create("Edit " + tableName, () => en))
{
audit.SetCustomField("UserGUID", userGUID);
en = dbEntry.CurrentValues.ToObject();
}
break;
default:
break;
}
return base.SaveChanges();