EF2.2 Core 2.2 Auditing returns 新旧值相同如何解决?
EF2.2 Core 2.2 Auditing returns same old and new value how to fix?
我正在尝试首先使用 EF 2.2 代码在我的 .net 核心 (2.2) 中实施审计 table。我的目的是记录在我跟随 this blog post 实施的我的实体中所做的所有更改。一切似乎都很好,但我得到了相同的旧值和新值。
请帮我找出错误。
这是我的控制器,我只分享其中的一部分
public class ProductController : Controller
{
private readonly MyDBContext _context;
private readonly IProduct productRepository;
public ProductController(MyECODBContext context,IProduct product)
{
_context = context;
productRepository = product;
}
//My Edit function
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("//my other bindings")] ECOViewModel vmECO,
string[] ApproversList, string[] ValidatorsList)
{ //POST method of the Edit Page
////My other logic
_context.Update(existingProduct);//updating product table
await _context.SaveChangesAsync(true);
}
}
以及我的上下文中的审计跟踪代码 class[此代码来自该博客 post]
在 case EntityState.Modified 的 switch case 中:我得到 property.OriginalValue 和 property.CurrentValue 相同的值;
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
var auditEntries = OnBeforeSaveChanges();
var result = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
await OnAfterSaveChanges(auditEntries);
return result;
}
private List<AuditEntry> OnBeforeSaveChanges()
{
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);
auditEntry.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();
}
private Task OnAfterSaveChanges(List<AuditEntry> auditEntries)
{
if (auditEntries == null || auditEntries.Count == 0)
return Task.CompletedTask;
foreach (var auditEntry in auditEntries)
{
// Get the final value of the temporary properties
foreach (var prop in auditEntry.TemporaryProperties)
{
if (prop.Metadata.IsPrimaryKey())
{
auditEntry.KeyValues[prop.Metadata.Name] = prop.CurrentValue;
}
else
{
auditEntry.NewValues[prop.Metadata.Name] = prop.CurrentValue;
}
}
// Save the Audit entry
Audits.Add(auditEntry.ToAudit());
}
return SaveChangesAsync();
}
}
这是一个已知问题,post 的评论部分甚至提到了它。为了将来参考,以下似乎对某些人有用
感谢您的post!我已经尝试使用它并想建议改进如何检测更新。在 Core EF 2.2 EntityState.Modified 上即使未修改字段也是如此,因此我添加了一些代码:
状态看起来已修改,即使实际上并未修改,因此您可以通过这种方式过滤掉不真实的案例。
case EntityState.Modified:
if (property.IsModified)
{
if(property.OriginalValue == null && property.CurrentValue == null)
continue;
if(property.OriginalValue == null ||
property.CurrentValue == null ||
!property.OriginalValue.Equals(property.CurrentValue))
{
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
}
看起来 from this issue here,您需要额外调用数据库才能成功实现您想要实现的目标。
我正在尝试首先使用 EF 2.2 代码在我的 .net 核心 (2.2) 中实施审计 table。我的目的是记录在我跟随 this blog post 实施的我的实体中所做的所有更改。一切似乎都很好,但我得到了相同的旧值和新值。
请帮我找出错误。
这是我的控制器,我只分享其中的一部分
public class ProductController : Controller
{
private readonly MyDBContext _context;
private readonly IProduct productRepository;
public ProductController(MyECODBContext context,IProduct product)
{
_context = context;
productRepository = product;
}
//My Edit function
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("//my other bindings")] ECOViewModel vmECO,
string[] ApproversList, string[] ValidatorsList)
{ //POST method of the Edit Page
////My other logic
_context.Update(existingProduct);//updating product table
await _context.SaveChangesAsync(true);
}
}
以及我的上下文中的审计跟踪代码 class[此代码来自该博客 post] 在 case EntityState.Modified 的 switch case 中:我得到 property.OriginalValue 和 property.CurrentValue 相同的值;
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
var auditEntries = OnBeforeSaveChanges();
var result = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
await OnAfterSaveChanges(auditEntries);
return result;
}
private List<AuditEntry> OnBeforeSaveChanges()
{
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);
auditEntry.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();
}
private Task OnAfterSaveChanges(List<AuditEntry> auditEntries)
{
if (auditEntries == null || auditEntries.Count == 0)
return Task.CompletedTask;
foreach (var auditEntry in auditEntries)
{
// Get the final value of the temporary properties
foreach (var prop in auditEntry.TemporaryProperties)
{
if (prop.Metadata.IsPrimaryKey())
{
auditEntry.KeyValues[prop.Metadata.Name] = prop.CurrentValue;
}
else
{
auditEntry.NewValues[prop.Metadata.Name] = prop.CurrentValue;
}
}
// Save the Audit entry
Audits.Add(auditEntry.ToAudit());
}
return SaveChangesAsync();
}
}
这是一个已知问题,post 的评论部分甚至提到了它。为了将来参考,以下似乎对某些人有用
感谢您的post!我已经尝试使用它并想建议改进如何检测更新。在 Core EF 2.2 EntityState.Modified 上即使未修改字段也是如此,因此我添加了一些代码:
状态看起来已修改,即使实际上并未修改,因此您可以通过这种方式过滤掉不真实的案例。
case EntityState.Modified:
if (property.IsModified)
{
if(property.OriginalValue == null && property.CurrentValue == null)
continue;
if(property.OriginalValue == null ||
property.CurrentValue == null ||
!property.OriginalValue.Equals(property.CurrentValue))
{
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
}
看起来 from this issue here,您需要额外调用数据库才能成功实现您想要实现的目标。