Как сохранить дочернюю сущность в EntityFramework 4?

У меня отношения 1-1 между Заказами и Контактом. то есть Contact.OrderId ссылается на заказы, а также является PK.

Итак, у меня есть существующий заказ, и я добавляю к нему новый контакт вот так...

    order.Contact = new Contact() { EmailAddress = "hello" };
    context.Orders.Attach(order);
    context.SaveChanges();

Произошло нарушение ограничения ссылочной целостности: значения свойств, определяющие ссылочные ограничения, не согласованы между главным и зависимыми объектами в отношении.

Так что я делаю неправильно?


person Ian Warburton    schedule 15.04.2011    source источник
comment
О, я понял! Заказ должен быть привязан к контексту прежде чем ему будет назначен контакт. В противном случае контекст не знает, что контакт был добавлен! Тогда даже не нужно устанавливать поле OrderId в контакте. Спасибо за помощь.   -  person Ian Warburton    schedule 18.04.2011


Ответы (4)


Просто создайте свою дочернюю сущность, установите ее свойство OrderIdReference, и все готово.

person Robert Koritnik    schedule 15.04.2011
comment
Кажется, работает. Но меня смущает поведение, о котором я упомянул в комментарии к исходному вопросу. - person Ian Warburton; 17.04.2011
comment
@Ian Warburton: Этот метод, который я предложил, является самым быстрым, и вы можете обойти определенные вызовы базы данных. Но то, что вы сделали, это то, что вы внесли некоторые изменения, прежде чем прикрепить свою сущность к конкретной записи БД. Вы всегда должны сначала прикрепить его, затем сделать все, что вам нужно, а затем зафиксировать все те изменения, которые вы сделали. - person Robert Koritnik; 17.04.2011
comment
Эй, Роберт, я беру свои слова обратно. Я допустил ошибку. Когда я устанавливаю OrderId для объекта Contact, объект Contact не сохраняется. Нужно ли в контексте указывать, что контакт новый? - person Ian Warburton; 18.04.2011
comment
Создайте новый Contact, задайте его свойства (включая OrderIdReference), добавьте его в таблицу контактов и сохраните. Так и должно быть, если в вашем заказе нет существующего контакта (поскольку вы говорите, что у вас есть ссылка 1-1). - person Robert Koritnik; 18.04.2011
comment
Нет.. у меня не работает. Нужно ли добавлять объект «Контакт» следующим образом: «context.Add (contactEntity);» потому что я имел в виду, что я могу добавить его к существующему заказу, «Прикрепить» заказ к контексту, и EF найдет новый контакт в заказе. - person Ian Warburton; 18.04.2011
comment
'context.Contacts.Add (contactEntity);' - person Ian Warburton; 18.04.2011
comment
@Ian: Я не могу точно сказать, в чем проблема, но вы всегда можете пойти по медленному пути: загрузить заказ из БД, добавить контакт и сохранить изменения. Это всегда работает. Но я предлагаю вам проверить и другие средства, потому что для этого требуется два обращения к БД. - person Robert Koritnik; 18.04.2011
comment
Ааа... возможно, имеет значение загрузка Ордена в одном контексте и сохранение в другом... - person Ian Warburton; 18.04.2011

У вас есть отношение 1-к-1 с общим первичным ключом в таблице Order и Contact: PK контакта всегда должен быть таким же, как PK связанного заказа. Это имеет некоторые последствия:

  • Только один из столбцов PK в таблицах Order и Contact может быть автоматически сгенерированным идентификатором. Я предполагаю, что это таблица Order.
  • Если order уже имел Contact до того, как вы назначили новый, вы должны явно удалить старый контакт из базы данных, потому что у вас не может быть двух контактов с одним и тем же OrderId, поскольку это PK одновременно.
  • Поскольку в таблице Contact нет столбца идентификаторов, вы должны указать ПК вручную в коде, и это должен быть ПК заказа.

Чтобы собрать это вместе, это может выглядеть так:

context.Orders.Attach(order);
if (order.Contact != null)
    context.DeleteObject(order.Contact);
order.Contact = new Contact() { OrderId = order.Id, EmailAddress = "hello" };
context.SaveChanges();

Это предполагает, что 1) старый order.Contact загружается в объект заказа, если уже был контакт до назначения нового, и 2) что свойство OrderId из Contact является свойством PK.

person Slauma    schedule 15.04.2011

Просто предположение, но я думаю, вам нужно установить pk для вашего контактного объекта. Entity framework не нравится, когда у вас нет первичных ключей null.

person BentOnCoding    schedule 15.04.2011

Новый контракт не добавлен:

context.Orders.Attach(order);
context.AddToContractSet(order.Contract);
context.SaveChanges();

Это предполагает, что order уже находится в БД, и вы подключаетесь, потому что он изначально пришел из другого контекста. Если нет, просто сделайте это:

context.AddToORdersSet(order);
context.SaveChanges();
person BlueRaja - Danny Pflughoeft    schedule 15.04.2011