#asp.net #entity-framework #ado.net
#asp.net #entity-framework #ado.net
Вопрос:
Мне нужно добавить несколько дочерних объектов к существующему родительскому объекту. Я создаю экземпляр своего родительского объекта и устанавливаю его ключ / идентификатор в моем слое обработки пользовательского интерфейса (к которому будут добавлены мои дочерние объекты).
Parent parenttoModify = new Parent();
parenttoModify.Parent_Id = 5; //this comes from some Index of a dropdown or a key column of a grid, i Have put a dummy value here for example
parenttoModify.Children.Add(child);
parenttoModify.Children.Add(child2);
DataAccess.ModifyParent(parenttoModify);
На моем уровне доступа к данным у меня есть метод, подобный :
public static bool ModifyParent(Parent parent)
{
int recordsAffected=0;
using (TestEntities testContext = new TestEntities())
{
testContext.Parents.Attach(parent);
var parentEntry = testContext.ObjectStateManager.GetObjectStateEntry(parent);
parentEntry.ChangeState(System.Data.EntityState.Modified);
recordsAffected = testContext.SaveChanges();
}
return recordsAffected > 0 ? true : false;
}
Я получаю сообщение об ошибке при TestContext.Родительский.Вызывается Attach (родительский). В нем говорится:
Объект с таким же ключом уже существует.
Я не уверен, почему это происходит, поскольку я не добавляю родительский объект, я просто прикрепляю его и добавляю дочерние объекты внутри него.
Есть идеи, где я ошибаюсь?
Ответ №1:
Куда вы добавляете детей? Я предполагаю, что вы показываете не весь код. Когда вы вызываете Attach
или AddObject
EF всегда присоединяет или добавляет все объекты из object graph, которые на данный момент неизвестны (отслеживаются) контексту. Исключение говорит о том, что некоторая сущность — возможно, родительская — уже отслеживается контекстом. Таким образом, у вас есть либо:
- Используемый общий контекст (вы создаете новый экземпляр в
ModifyParent
, поэтому это не должно быть обращением) - Сначала загрузите родительский элемент из контекста в
ModifyParent
- Вызывается
Attach
илиAddObject
для любого дочернего элемента перед присоединением родительского.
Все эти операции приводят к получаемому вами исключению.
Комментарии:
1. Я создаю экземпляры своих дочерних объектов на уровне обработки пользовательского интерфейса, поэтому в этом случае child и Child2 создаются перед добавлением их к родительским объектам
2. Исключение возникает, когда я добавляю несколько дочерних объектов (это проблема, которую я также выделил в своем вопросе). Если я просто добавлю один дочерний объект, программа успешно выполнится. У меня есть отношение «один ко многим» между родительской таблицей и дочерней таблицей в базе данных
3.@Kunal: Вы должны добавить
child
иchild2
кparenttoModify.Children
после того, как вы прикрепили родительский объект к контексту. В противном случае весь граф объектов — родительский плюс дочерние — будет привязан к контексту, как объяснил Ладислав. Это означает, чтоchild
иchild2
будут находиться не вAdded
состоянии, а в stateUnchanged
, поэтому EF рассматривает их как существующие объекты с допустимым ключом сущности. Поскольку вы создали дочерние объекты с нуля, их ключом, вероятно, будет0
(или любой другой по умолчанию). Итак, EF предполагает, что существуют две дочерние сущности с одинаковым ключом0
-> исключение!4. @Slauma: Одно за ваше объяснение, но это плохо с точки зрения дизайна, это означает, что мне нужно отправить отдельный список дочерних объектов с моего уровня обработки пользовательского интерфейса. Есть ли способ отправлять только родительские объекты и дочерние, прикрепленные к ним, вместо отправки отдельного списка дочерних объектов
5. @Kunal: Вы могли бы попробовать перебрать
Children
коллекцию и добавить каждый дочерний объект в контекст, прежде чем присоединять родительский. Обратите внимание, что дочерние объекты должны не иметь набора ссылок на родительский объект, иначе EF также добавила бы родительский объект в контекст. Вероятно, вы получите нового родителя для каждого дочернего объекта в базе данных. Не уверен, что это сработает, хотя.