Там нет необходимости переопределять SaveChanges.
Вы можете
Trigger Context.ChangeTracker.DetectChanges();
// может потребоваться в зависимости от вашего прокси подход
Затем проанализировать контекст перед сохранением. , вы можете ... добавить журнал изменений в CURRENT Unit of work. Таким образом, журнал сохраняется в одной транзакции COMMIT. Или обрабатывайте его так, как вы считаете нужным. Но сохранение журнала изменений в одно и то же время. гарантирует, что это ОДНА Сделка.
Анализ образца контекста: У меня есть простой инструмент для создания контекстного содержимого Dump для отладки вывода, поэтому, когда в отладчике я могу использовать немедленное окно для проверки содержимого. например Вы можете использовать это как стартер, чтобы подготовить свой журнал CHANGE. Попробуйте в ближайшем окне отладчика. У меня FULL дамп в моем классе Context.
Образец Немедленный вызов окна. UoW.Context.FullDump();
общественный недействительный FullDump() {
Debug.WriteLine("=====Begin of Context Dump=======");
var dbsetList = this.ChangeTracker.Entries();
foreach (var dbEntityEntry in dbsetList)
{
Debug.WriteLine(dbEntityEntry.Entity.GetType().Name + " => " + dbEntityEntry.State);
switch (dbEntityEntry.State)
{
case EntityState.Detached:
case EntityState.Unchanged:
case EntityState.Added:
case EntityState.Modified:
WriteCurrentValues(dbEntityEntry);
break;
case EntityState.Deleted:
WriteOriginalValues(dbEntityEntry);
break;
default:
throw new ArgumentOutOfRangeException();
}
Debug.WriteLine("==========End of Entity======");
}
Debug.WriteLine("==========End of Context======");
}
private static void WriteCurrentValues(DbEntityEntry dbEntityEntry)
{
foreach (var cv in dbEntityEntry.CurrentValues.PropertyNames)
{
Debug.WriteLine(cv + "=" + dbEntityEntry.CurrentValues[cv]);
}
}
private static void WriteOriginalValues(DbEntityEntry dbEntityEntry)
{
foreach (var cv in dbEntityEntry.OriginalValues.PropertyNames)
{
Debug.WriteLine(cv + "=" + dbEntityEntry.OriginalValues[cv]);
}
}
}
EDIT: получить изменения
Я использую эту процедуру, чтобы получить chnages ...
public class ObjectPair {
public string Key { get; set; }
public object Original { get; set; }
public object Current { get; set; }
}
public virtual IList<ObjectPair> GetChanges(object poco) {
var changes = new List<ObjectPair>();
var thePoco = (TPoco) poco;
foreach (var propName in Entry(thePoco).CurrentValues.PropertyNames) {
var curr = Entry(thePoco).CurrentValues[propName];
var orig = Entry(thePoco).OriginalValues[propName];
if (curr != null && orig != null) {
if (curr.Equals(orig)) {
continue;
}
}
if (curr == null && orig == null) {
continue;
}
var aChangePair = new ObjectPair {Key = propName, Current = curr, Original = orig};
changes.Add(aChangePair);
}
return changes;
}
редактировать- Если вы должны использовать отслеживание внутренних объектов.
var context = ???// YOUR DBCONTEXT class
// get objectcontext from dbcontext...
var objectContext = ((IObjectContextAdapter) context).ObjectContext;
// for each tracked entry
foreach (var dbEntityEntry in context.ChangeTracker.Entries()) {
//get the state entry from the statemanager per changed object
var stateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(dbEntityEntry.Entity);
var modProps = stateEntry.GetModifiedProperties();
Debug.WriteLine(modProps.ToString());
}
Я декомпилировал EF6. В результате модификации действительно используется частный бит-массив для отслеживания полей, которые изменили .
// EF decompiled source..... _modifiedFields is a bitarray
public override IEnumerable<string> GetModifiedProperties()
{
this.ValidateState();
if (EntityState.Modified == this.State && this._modifiedFields != null)
{
for (int i = 0; i < this._modifiedFields.Length; ++i)
{
if (this._modifiedFields[i])
yield return this.GetCLayerName(i, this._cacheTypeMetadata);
}
}
}
Phil - это отличный образец. Спасибо. Я обновил свой код выше, я не использую единицу работы. Итак, вы говорите, прежде чем я сэкономлю, я должен отслеживать изменения, чтобы сравнить два набора значений? также, если у меня разные репозитории, мне придется дублировать код? – user2206329
имеет много репозиториев в порядке. Код предназначен для контекста, поэтому его можно учесть. т.е. просто пройти в контексте. Рассмотрим подход «Единица работы», в котором вы контролируете сохранение, - это то, где можно управлять журналом изменений. причина, по которой существует шаблон UOW, заключается в том, чтобы избежать 500 методов сохранения в репозиториях ;-) –
phil - есть ли простой способ просто идентифицировать только измененные значения? В записи я могу изменить только одно поле. так же функция текущего значения отображает только элемент, который был изменен, или он отображает все поля для этой записи? – user2206329