сохранение нового объекта в DataServiceContext со связанными новыми объектами

#c# #.net #entity-framework #wcf #odata

#c# #.net #entity-framework #wcf #odata

Вопрос:

У меня есть служебная ссылка на класс DataServiceContext в моем клиентском проекте.

Мне нужно создать новый объект и сохранить его в контексте базы данных.

Все идет хорошо, пока я сохраняю только этот объект, без каких-либо связанных объектов.

 A a = new A();
context.AddToAs(a);
context.BeginSaveChanges(o=>{
    //some after-save code there
}, null);
 

Однако код, подобный этому:

 A a = new a(); //parent entity
B b = new b(); //child entity which has corresponding b.A navigation
               //property and b.AId field for referencing 'A' entity primary
               //key.
a.b = b;
context.AddToAs(a);
context.AddToBs(b);
context.SetLink(b, "A", a);
context.BeginSaveChanges(o=>{
    //some after-save code here
}, null);
 

… сбой с ошибкой «Оператор INSERT конфликтует с ограничением ВНЕШНЕГО КЛЮЧА».

Конечно, я понимаю, что вновь созданный объект «A» имеет первичный ключ, равный «0», и соответствующие свойства навигации в объекте «B», например b.Помощь также равна «0» при сохранении. И это действительно вызывает проблему — «Объект» с первичным ключом «0» уже существует в базе данных.

Итак, я должен сначала сохранить объект «A», без присвоения каких-либо связанных объектов «B», чтобы объект «A» был сохранен и получил реальный идентификатор, а затем — присоединить объекты «B» к A и сохранить контекст еще раз, чтобы объекты «B» были сохранены.

Я более чем уверен, что я делаю там что-то ужасно неправильное, кто-нибудь может дать какие-либо предложения о том, как сделать это с помощью одного SaveChanges?

Ответ №1:

Я столкнулся с той же проблемой. Мое решение состояло в том, чтобы не связывать объекты в памяти. Я использовал только context.SetLink. Итак, для вашего примера, я думаю, это сработает:

 A a = new a(); //parent entity
B b = new b(); //child entity which has corresponding b.A navigation
               //property and b.AId field for referencing 'A' entity primary
               //key.
// Omit this line. a.b = b;
context.AddToAs(a);
context.AddToBs(b);
context.SetLink(b, "A", a);
context.BeginSaveChanges(o=>{
    //some after-save code here
}, null);
 

В моей ситуации созданные объекты не использовались после вызова save changes, поэтому не имело значения, что объекты не были связаны в памяти после вызова save. Если вам нужно, чтобы объекты также были связаны в памяти после вызова save, я могу попробовать две вещи:

  • Загрузите объекты из контекста после их сохранения. Это немного ненужный вызов базы данных, но это означает, что загруженные объекты будут иметь правильную привязку.
  • Вручную назначьте ассоциации (например, a.b = b;) после сохранения изменений.