Entity Framework 4.3.1, DbContext Добавление объекта с существующим ссылочным объектом - PullRequest
1 голос
/ 14 марта 2012

(прежде всего извините за плохой английский)

Я новичок в структуре сущностей и немного тестирую. Предположим, у меня есть 2 объекта, которые являются объектами POCO. Персона и адрес.

Мой сценарий состоит в том, что я хочу добавить нового человека в DbContext, который имеет ссылку на уже существующий объект. Связь между обеими сущностями является отношением «многие: многие».

 using ( var t = new Tww.SV.Models.Model.Portal.SVPortalEntities() )
 {
       testaddress = ( from c in t.Adresses
                       select c ).ToList().FirstOrDefault();
 }

 var newPerson = new Person();
 newPerson.Name = "Henry";
 newPerson.Adresses.Add( testaddress );

 using ( var k = new Tww.SV.Models.Model.Portal.SVPortalEntities() )
 {
       k.Persons.Add(newPerson);
       k.SaveChanges();
 }

Проблема, с которой я столкнулся сейчас, заключается в том, что после добавления пользователя будет создан дополнительный адрес (с теми же значениями, но с новым ключом). Как я могу добавить существующую ссылку на новый объект вместо создания нового?

Ответы [ 3 ]

2 голосов
/ 14 марта 2012

Использовать один контекст для всей операции:

 using ( var t = new Tww.SV.Models.Model.Portal.SVPortalEntities() )
 {
       testaddress = ( from c in t.Adresses
                       select c ).ToList().FirstOrDefault();
       var newPerson = new Person();
       newPerson.Name = "Henry";
       newPerson.Adresses.Add( testaddress );
       k.Persons.Add(newPerson);
       k.SaveChanges();
 }

Если вы не можете этого сделать, вам нужно вручную изменить состояние существующего адреса в новом контексте через ObjectStateManager или аналогичный.

1 голос
/ 14 марта 2012

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

Однако это распространенная проблема, особенно когдаиспользование классов EF в таких сервисах, как WCF.Лучшее решение, которое я нашел, это «исправить» поступающие новые объекты перед их сохранением.Я буду первым администратором, я нахожу это "уродливым", но мне также не удалось найти какие-либо лучшие варианты, которые действительно работают все время.Я обычно помещаю ссылочный код повторной ассоциации в метод в другом частичном сегменте моего класса сущностей:

public void FixUp(EntityContext c)
{
  for (int i = 0; i < this.Addresses.Count; i++)
  {
    var existing = c.Addresses.SingleOrDefault(a => a.Id = this.Addresses[i].Id);
    if (existing != null)
    {
      this.Addresses[i] = existing;
    }
  }
}

using (var k = new EntityContext())
{
  newPerson.FixUp(k);
  k.Persons.Add(newPerson);
  k.SaveChanges();
}
0 голосов
/ 14 марта 2012

Чтобы объяснить, почему это происходит: вы создаете два DbContexts.Во-первых, вы получаете адрес объекта.Затем, вне какой-либо области контекста (см. Ваш с использованием ), вы создаете нового отдельного человека.Это не относится ни к одному из ваших двух контекстов.Следующее, что происходит, это то, что вы создаете новый контекст и добавляете к нему свой объект Person .

Этот контекст теперь не знает ваш новый Person (это было"вне области видимости", или Отдельно ), ни ваш Адрес (Это из другого контекста).Обе сущности будут добавлены и помечены как таковые в ChangeTracker, Added .

У вас есть несколько решений:

  • Сначала используйте только один контекст для получения Адреса , создайте Персона ви Добавьте это.Для этого вам нужно немного изменить свой код, и он может не сработать, если вы работаете над сервисными сценариями.

  • Во-вторых, если у вас нет шансов изменить этокод, и вам нужно прикрепить отдельные объекты, как вы делаете в своем фрагменте кода, вы можете переопределить SaveChanges вашего класса Context и перебрать сущности в ChangeTracker .Те, которые уже сохранены (Id> 0), могут быть установлены на «Без изменений» или, если вы хотите сохранить в конечном итоге внесенные изменения, «Изменено».Это ужасно, но это должно сработать.

...