DbContext SaveChanges () - Обнаружение обновленных сущностей

Я переопределил метод SaveChanges () в классе Entity Framework 4.1 DbContext.

Мое переопределение выглядит так:

public override int SaveChanges() {

    IEnumerable<DbEntityEntry> modifiedEntityEntries = ChangeTracker.Entries().Where( e => e.State == EntityState.Modified );

    Debug.Assert( modifiedEntityEntries.Count() == 2 );

    int savedChanges = base.SaveChanges();

    Debug.Assert( savedChanges == 1 );

    // HELP! At this point, how do I tell Which of the two "Modified" entities actually updated a row in the database?

    return savedChanges;

}

Предположим, что в контексте есть 2 объекта, и оба помечены как измененные (EntityState.Modified). Одна из них была изменена и отличается от базовой строки базы данных. Другая на самом деле не отличается от базовой строки базы данных, она просто была отмечена как таковая.

Как мне сказать после вызова SaveChanges (), какая из двух сущностей действительно обновила строку в базе данных, а какая не была изменена в конце концов?


person FantasticJamieBurns    schedule 14.11.2011    source источник


Ответы (1)


Так мы делаем наш код. Включена отложенная загрузка и создание прокси.

Обратите внимание, что при включении создания прокси EF будет знать, какое свойство изменилось, вам не нужно переходить в базу данных. Единственное место, о котором EF не знает, - это если какой-то другой контекст изменил строку (ошибка параллелизма), чтобы избежать использования столбца / свойства RowVersion.

В конструкторе:

  public DataContext()
            : base()
  {
      this.Configuration.ProxyCreationEnabled = true;
      this.Configuration.LazyLoadingEnabled = true;
      var objectContext = ((IObjectContextAdapter)this).ObjectContext;
      objectContext.SavingChanges += new EventHandler(objectContext_SavingChanges);
  }

  private void objectContext_SavingChanges(object sender, EventArgs e)
  {
      var objectContext = (ObjectContext)sender;
      var modifiedEntities =
            objectContext.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added
            | System.Data.EntityState.Modified);

      foreach (var entry in modifiedEntities)
      {
          var entity = entry.Entity as BusinessBase;
          if (entity != null)
          {
              entity.ModDateTime = DateTime.Now;
              entity.ModUser = Thread.CurrentPrincipal.Identity.Name;
          }
      }
  }
person np-hard    schedule 14.11.2011
comment
Ни создание прокси, ни ленивая загрузка не включены. Однако мне было бы все равно! Я применяю аудит ко всем обновлениям базы данных и имею бизнес-требование, чтобы регистрировались только те объекты, которые фактически приводят к изменению базы данных. Я мог бы попробовать RowVersion, но мне кажется неправильным добавлять столбец в базу данных только для этой цели. Я также мог сначала загрузить базовый объект из базы данных и сравнить. Кажется, что DbContext знает, что был обновлен только 1, и я подумал, есть ли способ узнать, какой именно из контекста. - person FantasticJamieBurns; 15.11.2011
comment
Я обновил свой ответ с помощью образца кода. BusinessBase - это наш базовый класс для всех сущностей. - person np-hard; 15.11.2011