C# 重写SaveChangesSync实体框架6以记录修改的属性值

C# 重写SaveChangesSync实体框架6以记录修改的属性值,c#,asp.net-mvc,entity-framework,entity-framework-6,C#,Asp.net Mvc,Entity Framework,Entity Framework 6,我正在开发一个ASP.NET核心项目,其中在SaveChanges中,我需要记录更新的值 根据,我试图覆盖savechangesync,但出现以下错误: 无法将“MyProject.ApplicationDbContext”类型的对象强制转换为“System.Data.Entity.Infrastructure.IObjectContextAdapter”类型 代码: public override Task savechangessync(CancellationToken Cancellat

我正在开发一个ASP.NET核心项目,其中在
SaveChanges
中,我需要记录更新的值

根据,我试图覆盖
savechangesync
,但出现以下错误:

无法将“MyProject.ApplicationDbContext”类型的对象强制转换为“System.Data.Entity.Infrastructure.IObjectContextAdapter”类型

代码:

public override Task savechangessync(CancellationToken CancellationToken=default)
{
ChangeTracker.DetectChanges();
ObjectContext ctx=((IObjectContextAdapter)this).ObjectContext;
列表objectStateEntryList=ctx.ObjectStateManager
.GetObjectStateEntries((System.Data.Entity.EntityState)(EntityState.Added | EntityState.Modified | EntityState.Deleted))
.ToList();
foreach(objectStateEntryList中的ObjectStateEntry条目)
{
如果(!entry.IsRelationship)
{
开关(进入状态)
{
案例(System.Data.Entity.EntityState)EntityState.Add:
//写日志。。。
打破
案例(System.Data.Entity.EntityState)EntityState.Deleted:
//写日志。。。
打破
案例(System.Data.Entity.EntityState)EntityState.Modified:
foreach(entry.GetModifiedProperties()中的字符串propertyName)
{
DbDataRecord original=entry.OriginalValues;
字符串oldValue=original.GetValue(original.GetOrdinal(propertyName)).ToString();
CurrentValueRecord current=entry.CurrentValues;
字符串newValue=current.GetValue(current.GetOrdinal(propertyName)).ToString();
if(oldValue!=newValue)//可能不需要
{
var a=string.Format(“条目:{0}原始:{1}新:{2}”,
entry.Entity.GetType().Name,
旧价值,新价值);
}
}
打破
}
}
}
返回base.saveChangesSync();
}
我还试图在Action方法中组合日志字符串,但我得到了相同的错误

public async Task<IActionResult> Edit(MyModel model)
{
    ...
    // _context is ApplicationDbContext()
    var myObjectState = _context.ObjectStateManager.GetObjectStateEntry(model);
    var modifiedProperties = myObjectState.GetModifiedProperties();

    foreach (var propName in modifiedProperties)
    {
        Console.WriteLine("Property {0} changed from {1} to {2}",
                          propName,
                          myObjectState.OriginalValues[propName],
                          myObjectState.CurrentValues[propName]);
    }
}
公共异步任务编辑(MyModel)
{
...
//_上下文为ApplicationDbContext()
var myObjectState=_context.ObjectStateManager.GetObjectStateEntry(模型);
var modifiedProperties=myObjectState.GetModifiedProperties();
foreach(modifiedProperties中的变量propName)
{
WriteLine(“属性{0}从{1}更改为{2}”,
propName,
myObjectState.OriginalValues[propName],
myObjectState.CurrentValues[propName]);
}
}
我用的是EF6

我需要记录属性名、旧值和新值。我不明白为什么我会犯这样的错误,我做错了什么

我做错了什么

使用EF 4.1中的示例:)

你可以利用EF 6中的ChangeTracker来完成你想要的东西。我建议为日志设置一个单独的DbContext,根据需要只包含日志表和FK:

在SaveChanges/SaveChangesSync覆盖中:

var updatedEntities = ChangeTracker.Entries()
    .Where(x => x.State == EntityState.Modified);

var insertedEntities = ChangeTracker.Entries()
    .Where(x => x.State == EntityState.Added);
从这里,您可以分别通过
OriginalValues
CurrentValues
访问原始和修改的属性值

**更新** 报告更改时,典型的简单方法是对OriginalValues和CurrentValues使用
ToObject()
,然后序列化为类似于Json的内容,以捕获相关对象的前后状态。但是,这将显示所有已修改和未修改的值

要遍历这些值以查找实际更改,需要更多的工作:

foreach(var entity in updatedEntities)
{
    foreach (var propertyName in entity.OriginalValues.PropertyNames)
    {
        if (!object.Equals(entity.OriginalValues.GetValue<object>(propertyName), 
        entity.CurrentValues.GetValue<object>(propertyName)))
        {
            var columnName = propertyName;
            var originalValue = entity.OriginalValues.GetValue<object>(propertyName)?.ToString() ?? "#null";
            var updatedValue = entity.CurrentValues.GetValue<object>(propertyName)?.ToString() ?? "#null";
            var message = $"The prop: {columnName} has been changed from {originalValue} to {updatedValue}";
        }
    }
}
foreach(updateTities中的var实体)
{
foreach(entity.OriginalValues.PropertyNames中的var propertyName)
{
如果(!object.Equals(entity.OriginalValues.GetValue(propertyName)),
entity.CurrentValues.GetValue(propertyName)))
{
var columnName=propertyName;
var originalValue=entity.OriginalValues.GetValue(propertyName)?.ToString()?“#null”;
var updatedValue=entity.CurrentValues.GetValue(propertyName)?.ToString()??“null”;
var message=$“属性:{columnName}已从{originalValue}更改为{updatedValue}”;
}
}
}

如何获取属性名称、旧值和新值?我做了一个foreach循环,其中我循环通过的每个实体,我试图组成如下字符串:
string.Format(“prop:{0}已从{1}更改为{2}”、prop.ToString()、prop.OriginalValues、prop.CurrentValues)我已在答案上展开,以提供用于生成更改历史记录的选项。OriginalValues不包含PropertyNames。我已经试过了。如果将整个对象传递给
context.Update(objectToUpdate)
,会发生什么情况原始值和当前值是否相同?我使用的是EF 6,我可以从原始值中访问PropertyNames。确保您使用的是
var updatedities=ChangeTracker.Entries(),其中(x=>x.State==EntityState.Modified)。。如果您使用的是EF Core而不是EF 6,则原始值具有
属性
,这些属性是包含
.Name
属性的对象。我不建议使用
context.Update(objectToUpdate)
,因为这会为所有列生成一条Update语句,无论它们是否更改。如果您想跟踪更新,最好让EF change tracker管理更新。
foreach(var entity in updatedEntities)
{
    foreach (var propertyName in entity.OriginalValues.PropertyNames)
    {
        if (!object.Equals(entity.OriginalValues.GetValue<object>(propertyName), 
        entity.CurrentValues.GetValue<object>(propertyName)))
        {
            var columnName = propertyName;
            var originalValue = entity.OriginalValues.GetValue<object>(propertyName)?.ToString() ?? "#null";
            var updatedValue = entity.CurrentValues.GetValue<object>(propertyName)?.ToString() ?? "#null";
            var message = $"The prop: {columnName} has been changed from {originalValue} to {updatedValue}";
        }
    }
}