Сначала перехват и регистрация изменений с кодом EF 4.2 - PullRequest
2 голосов
/ 02 декабря 2011

Я потратил некоторое время на чтение нескольких постов и статей об отслеживании аудита, но все еще не могу понять это.

Мне нужна довольно простая система аудита, которая даст мне такие результаты, как:

  • Клиент "Джон Доу" удален пользователем "
  • Клиент "Jane Doe" создан "Other User"
  • Адрес пользователя "John Doe" был изменен пользователем "
  • Клиент "Джейн Доу" был удален "другим пользователем"

Я попытался переопределить событие SaveChanges в dbContext, но застрял со следующей проблемой:

public override int SaveChanges()
{

        foreach (DbEntityEntry<IAuditable> entry in ChangeTracker.Entries<IAuditable>())
        {
            if (entry.State == EntityState.Added)
            {
                // since the object was not added yet, if I write to log in here and
                // for some reason SaveChanges fail, I will end up with a fake log entry
            }
            else if (entry.State == EntityState.Modified)
            {
                // same in here
            }
        }

        return base.SaveChanges();

        // here the state for all entries have changed to Unchanged or Detached.
        // detached is probably the one that was deleted however the “Unchanged”
        // could be new or modified records.
}

Я знаю, что мог бы использовать триггеры в базе данных для достижения этой цели, но я бы хотел оставить ее здесь, чтобы иметь больше контроля над ней, так как я не SQL-парень и после развертывания приложения у меня не будет так много контроля над БД.

Я уверен, что мне здесь не хватает чего-то очень простого. Я ценю любую помощь.

Заранее спасибо.

1 Ответ

2 голосов
/ 02 декабря 2011

Вы всегда можете проверить, есть ли какие-либо записи аудита в вашем контексте, и удалить их при вызове SaveChanges.Это решит вашу первую проблему - вы всегда будете удалять предыдущие записи аудита перед созданием новой.

Вторая проблема не может быть решена с помощью API DbContext.DbContext API - это упрощение ObjectContext API, и это упрощение удаляет методы, необходимые для сложных сценариев.Одним из таких методов является перегруженная версия SaveChanges с возможностью не принимать изменения (не изменять состояния сущностей).

Вы можете конвертировать DbContext в ObjectContext через IObjectContextAdapter.Даже с ObjectContext это не будет прямым:

// If you want to have audits in transaction with records you must handle
// transactions manually
using (TransactionScope scope = new TransactionScope(...))
{
    ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
    context.SaveChanges(SaveOptions.DetectChangesBeforeSave);

    var audits = new List<Audit>();

    // Now you must call your audit code but instead of adding audits to context
    // you must add them to list. 

    // This is the reason why you must not add changes to context. You must accept
    // old changes prior to adding your new audit records otherwise EF will perform
    // changes again. If you add your entities to context and call accept before 
    // saving them your changes will be lost
    context.AcceptAllChanges();

    // Now add all audits from list to context

    context.SaveChanges();

    // Complete the transaction
    scope.Complete(); 
}
...