Getting all changes made to an object in the Entity Framework
Is there a way to get all the changes made to a object in the Entity Framework before it saves all changes. The reason for this is that i want to create a log table in our clients database:
so...
Is there a way to get the current database values(old) and the new values(current) before changes are saved?
If not, how can i achieve this in a generic way, so all my View Models can inherit from this?(I am using the MVVM + M Structure)
You can use ObjectContext's ObjectStateManager,GetObjectStateEntry to get an object's ObjectStateEntry, which holds its original and current values in the OriginalValues and CurrentValues properties. You can get the names of the properties that changed using the GetModifiedProperties method.
You can write something like:
var myObjectState=myContext.ObjectStateManager.GetObjectStateEntry(myObject);
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]);
}
对于EF5,您可以在SaveChanges()方法中记录您的更改,如下所示:
public override int SaveChanges()
{
var changes = from e in this.ChangeTracker.Entries()
where e.State != System.Data.EntityState.Unchanged
select e;
foreach (var change in changes)
{
if (change.State == System.Data.EntityState.Added)
{
// Log Added
}
else if (change.State == System.Data.EntityState.Modified)
{
// Log Modified
var item = change.Cast<IEntity>().Entity;
var originalValues = this.Entry(item).OriginalValues;
var currentValues = this.Entry(item).CurrentValues;
foreach (string propertyName in originalValues.PropertyNames)
{
var original = originalValues[propertyName];
var current = currentValues[propertyName];
if (!Equals(original, current))
{
// log propertyName: original --> current
}
}
}
else if (change.State == System.Data.EntityState.Deleted)
{
// log deleted
}
}
// don't forget to save
base.SaveChanges();
}
I use this extension function that provides details on the entity being changed, the old and new values, the datatype, and the entity key.
This is tested with EF6.1 using ObjectContext and uses log4net for output.
/// <summary>
/// dump changes in the context to the debug log
/// <para>Debug logging must be turned on using log4net</para>
/// </summary>
/// <param name="context">The context to dump the changes for</param>
public static void DumpChanges(this ObjectContext context)
{
context.DetectChanges();
// Output any added entries
foreach (var added in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
{
Log.DebugFormat("{0}:{1} {2} {3}", added.State, added.Entity.GetType().FullName, added.Entity.ToString(), string.Join(",", added.CurrentValues.GetValue(1), added.CurrentValues.GetValue(2)));
}
foreach (var modified in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
{
// Put original field values into dictionary
var originalValues = new Dictionary<string,int>();
for (var i = 0; i < modified.OriginalValues.FieldCount; ++i)
{
originalValues.Add(modified.OriginalValues.GetName(i), i);
}
// Output each of the changed properties.
foreach (var entry in modified.GetModifiedProperties())
{
var originalIdx = originalValues[entry];
Log.DebugFormat("{6} = {0}.{4} [{7}][{2}] [{1}] --> [{3}] Rel:{5}",
modified.Entity.GetType(),
modified.OriginalValues.GetValue(originalIdx),
modified.OriginalValues.GetFieldType(originalIdx),
modified.CurrentValues.GetValue(originalIdx),
modified.OriginalValues.GetName(originalIdx),
modified.IsRelationship,
modified.State,
string.Join(",", modified.EntityKey.EntityKeyValues.Select(v => string.Join(" = ", v.Key, v.Value))));
}
}
// Output any deleted entries
foreach (var deleted in context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted))
{
Log.DebugFormat("{1} {0} {2}", deleted.Entity.GetType().FullName, deleted.State, string.Join(",", deleted.CurrentValues.GetValue(1), deleted.CurrentValues.GetValue(2)));
}
}
链接地址: http://www.djcxy.com/p/5730.html
上一篇: 我如何获得实体框架中插入的实体的Id?
下一篇: 获取对实体框架中的对象所做的所有更改