我正在使用EF Core / .NET Core 2.1,并遵循DDD。我需要对我的实体的所有更改实施审核日志,并且已经使用this blog post中的代码(下面包含了该帖子的相关代码)来实现。该代码可以工作并跟踪对任何属性的更改,但是,当它记录对我的值对象的更改时,它仅列出新值,而没有列出旧值。
某些代码:
public class Item
{
protected Item(){}
//truncated for brevity
public Weight Weight { get; private set; }
}
public class Weight : ValueObject<Weight>
{
public WeightUnit WeightUnit { get; private set; }
public double WeightValue { get; private set; }
protected Weight() { }
public Weight(WeightUnit weightUnit, double weight)
{
this.WeightUnit = weightUnit;
this.WeightValue = weight;
}
}
以及上下文类中的审核跟踪代码
public class MyContext : DbContext
{
//truncated for brevity
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
var auditEntries = OnBeforeSaveChanges();
var result = base.SaveChanges(acceptAllChangesOnSuccess);
OnAfterSaveChanges(auditEntries);
return result;
}
private List<AuditEntry> OnBeforeSaveChanges()
{
if (!this.AuditingAndEntityTimestampingEnabled)
{
return null;
}
ChangeTracker.DetectChanges();
var auditEntries = new List<AuditEntry>();
foreach (var entry in ChangeTracker.Entries())
{
if (entry.Entity is Audit || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged)
{
continue;
}
var auditEntry = new AuditEntry(entry)
{
TableName = entry.Metadata.Relational().TableName
};
auditEntries.Add(auditEntry);
foreach (var property in entry.Properties)
{
if (property.IsTemporary)
{
// value will be generated by the database, get the value after saving
auditEntry.TemporaryProperties.Add(property);
continue;
}
string propertyName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
{
auditEntry.KeyValues[propertyName] = property.CurrentValue;
continue;
}
switch (entry.State)
{
case EntityState.Added:
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
case EntityState.Deleted:
auditEntry.OldValues[propertyName] = property.OriginalValue;
break;
case EntityState.Modified:
if (property.IsModified)
{
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
}
break;
}
}
}
// Save audit entities that have all the modifications
foreach (var auditEntry in auditEntries.Where(_ => !_.HasTemporaryProperties))
{
Audits.Add(auditEntry.ToAudit());
}
// keep a list of entries where the value of some properties are unknown at this step
return auditEntries.Where(_ => _.HasTemporaryProperties).ToList();
}
}
这是审核更改如何持久保存到数据库的屏幕快照。 Item上的非值对象属性列出了它们的旧值/新值,其中对值对象的更改仅列出了新值:
是否可以获取值对象的先前值?
更新:
因此,对于我的值对象所做的更改,OldValues列为null的原因是由于对 Added 进行更改时,值对象的状态。我在switch语句中添加了对IsOwned()方法的调用,并尝试像下面这样来获取property.OriginalValue:
case EntityState.Added:
if (entry.Metadata.IsOwned())
{
auditEntry.OldValues[propertyName] = property.OriginalValue;
}
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
但是,这只是记录值对象被更新到的当前值。
所以问题仍然存在-是否有任何方法可以使用EF Core ChangeTracker获取值对象的先前值,或者由于我的审核要求,我是否需要重新考虑使用DDD价值对象?
答案 0 :(得分:0)
代替
auditEntry.OldValues[propertyName] = property.OriginalValue;
使用
auditEntry.OldValues[propertyName] = entry.GetDatabaseValues().GetValue<object>(propertyName).ToString();