Проблема параллелизма Entity Framework - PullRequest
2 голосов
/ 24 мая 2011

У меня проблема с управлением параллелизмом с Entity Framework.

Я определил класс Person (Покажу только интересные детали)

public class Person
{
   public Guid Id { get; set; }
   public string Name { get; set; }

   public Guid? CategoryId { get; set; }
   public virtual Category Category { get; set; }

   public byte[] TimeStamp { get; set; }
}

и класс для настройки

public class PersonConfiguration : EntityTypeConfiguration<Person>
{
   public PersonConfiguration() : base()
   {
      HasKey(p => p.Id);
      Property(p => p.Id)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

      Property(p => p.TimeStamp)
         .IsConcurrencyToken()
         .HasColumnType("timestamp")
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
   }
}

Точно так же я определил класс Category и соответствующий класс для настройки

public class Category
{
   public Guid Id { get; set; }
   public string Title { get; set; }

   public byte[] TimeStamp { get; set; }
}

public class CategoryConfiguration : EntityTypeConfiguration<Category>
{
   public CategoryConfiguration() : base()
   {
      HasKey(c => c.Id);
      Property(c => c.Id)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

      Property(c => c.TimeStamp)
         .IsConcurrencyToken()
         .HasColumnType("timestamp")
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
   }
}

В методе CommitChanges я ловлю исключение DbUpdateConcurrencyException исключение и с помощью стратегии «выигрыши базы данных» я перезагружаю сущность из БД.

public int CommitChanges()
{
  ret = -1;

  try
   {
      ret = _context.SaveChanges();
   }
   catch (DbUpdateConcurrencyException e)
   {
      (e as DbUpdateConcurrencyException).Entries.Single().Reload();
      throw new UowUpdateConcurrencyException();
   }
   catch (Exception e)
   {
         throw new Exception(e.Message);
   }

   return ret;
}

Для целей этого вопроса мы предполагаем, что за один раз в БД сохраняется только одна сущность

Нет проблем, если я сохраню категорию. Все тесты в порядке.

Проблема возникает, когда я пытаюсь сохранить человека (ранее загруженного через тот же контекст) и есть нарушение параллелизма. Я отлаживаю эту строку

(e as DbUpdateConcurrencyException).Entries.Single().Reload();

Сюрприз. Исключение выдается правильно, но объект, который появляется из БД имеет тип Категория вместо Персона.

Категория возврата.

(e as DbUpdateConcurrencyException).Entries.ToList()[0].Entity.GetType()

Если я отключу проверку параллелизма для категории, удалив свойство Timestamp в в классе Category все отлично работает

Я думаю, что есть некоторая проблема со свойством навигации, которое я определил в классе Person.

Что вы думаете?

Спасибо!

UPDATE

Кажется, проблема в том, что я установил привязку между ComboBox и свойством Category.

Если я это прокомментирую, все работает нормально

<ComboBox ItemsSource="{Binding Path=CategoryList}"
          DisplayMemberPath="Title"
          SelectedValuePath="Id"
          SelectedItem="{Binding Path=Category, Mode=TwoWay}" />

Если я связываю комбо с CategoryId, а не с Category, проблема все равно остается.

<ComboBox ItemsSource="{Binding Path=CategoryList}"
          DisplayMemberPath="Title"
          SelectedValuePath="Id"
          SelectedValue="{Binding Path=CategoryId, Mode=TwoWay}" />

1 Ответ

1 голос
/ 25 мая 2011

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

Решение состоит в том, чтобы загрузить CategoryList, который является ItemsSource для комбинированного списка, в другом контексте, чем тот, который используется для Person и для операции сохранения. Это предотвращает включение категории в область сохранения.

Наконец, мы должны установить привязку к свойству CategoryId, а не к свойству Category.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...