Entity Framework не сохраняет изменения в новой сущности с двухуровневой связью

Я создаю сайт ASP.NET MVC с помощью ADO.NET Entity Framework. У меня есть модель объекта, которая включает эти объекты, связанные внешними ключами:

Отчет(ID, Дата, Заголовок, Report_Type_ID и т.д.)

  • SubReport(ID, ReportText, etc.) - one-to-one relationship with Report.
    • ReportSource(ID, Name, Description) - one-to-many relationship with Sub_Report.
      • ReportSourceType(ID, Name, Description) - one-to-many relationship with ReportSource.
      • Контакт (идентификатор, имя, адрес и т. д.) — отношение один к одному с Report_Source.

Для каждого типа вложенного отчета существует страница Create.aspx. Метод публикации события возвращает новую сущность Sub_Report.

Раньше в моем методе публикации я следовал этому процессу:

  1. Задайте свойства для нового объекта отчета в полях страницы.
  2. Задайте конкретные свойства объекта SubReport из полей страницы.
  3. Установите отчет объекта SubReport на новый объект отчета, созданный в 1.
  4. Учитывая идентификатор, предоставленный страницей, найдите ReportSource и установите ReportSource сущности Sub_Report на найденную сущность.
  5. Сохранить изменения.

Этот рабочий процесс успешно работал в течение нескольких недель. Затем на прошлой неделе что-то изменилось, и он больше не работает. Теперь вместо операции сохранения я получаю это исключение:

UpdateException: "Entities in 'DIR2_5Entities.ReportSourceSet' 
participate in the 'FK_ReportSources_ReportSourceTypes' relationship. 
0 related 'ReportSourceTypes' were found. 1 'Report_Source_Types' is expected."

Визуализатор отладки показывает следующее:

  • ReportSource SubReport установлен и загружен, и все его свойства верны.
  • Report_Source имеет прикрепленную допустимую сущность ReportSourceType.

В SQL Profiler подготовленный оператор SQL выглядит нормально. Может ли кто-нибудь указать мне, какую очевидную вещь мне не хватает?

ТИА

Примечания: в этом случае отчет и вложенный отчет всегда являются новыми объектами. Сущность отчета содержит свойства, общие для многих типов отчетов, и используется для общих запросов. SubReports — это специальные отчеты с дополнительными параметрами, различающимися по типу. На самом деле для каждого типа SubReport существует свой набор сущностей, но этот вопрос относится ко всем из них, поэтому я использую SubReport в качестве упрощенного примера.


person Tim Rourke    schedule 17.08.2009    source источник
comment
Возможно, вы захотите дать фрагмент кода, это определенно поможет мне понять, что происходит. Обычно такие проблемы намного легче увидеть с помощью некоторого кода.   -  person Alex James    schedule 18.08.2009
comment
Спасибо за ответ, Алекс. Я постараюсь опубликовать код позже. На данный момент я просто пометил его как EF 1.0 и заменил свой код хранимой процедурой.   -  person Tim Rourke    schedule 18.08.2009


Ответы (6)


Обычно это происходит, если ваши таблицы базы данных имеют связь 1-1 друг с другом. В вашем примере reportsourceset ожидает тип отчетов с любым идентификатором, на который он ссылается. Я столкнулся с этой проблемой, когда мои отношения связывают два первичных ключа из противоположных таблиц вместе.

person Ramone Hamilton    schedule 02.12.2009
comment
Я просто удалил самосоединение, и вставка сработала. Будет ли это работать в общей схеме вещей? - person Rod; 29.09.2011

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

Вот что нужно проверить:

  • Установите точку останова на вызове SaveChanges() и тщательно изучите контекст объекта. Вы должны увидеть список дополнений и изменений контекста. При первом просмотре я обнаружил, что он пытается добавить все мои связанные объекты, а не просто указывает на них. В вашем случае контекст может пытаться добавить новый Report_Source_Type.
  • Связано с предыдущим пунктом, но если вы извлекаете источник отчета, убедитесь, что он извлекается из базы данных по его ключу сущности и правильно привязан к контексту. В противном случае ваш контекст может считать, что это новый элемент, и поэтому его требуемые отношения не будут установлены.

Из памяти я извлек свои ссылки с помощью метода context.GetObjectByKey, а затем явно прикрепил эти объекты к контексту с помощью метода context.Attach, прежде чем назначать их свойствам моего исходного объекта.

person Damovisa    schedule 25.02.2010
comment
Список дополнений и изменений можно найти с помощью подсказки по данным Visual Studio (установите точку останова на строке, аналогичной приведенной ниже, и наведите указатель мыши на часть ObjectContext). this.ObjectContext.SaveChanges(). В подсказке по данным перейдите к «_addedEntityStore» через... base {System.Data.Objects.ObjectContext } -> ObjectStateManager -> Non-Public Members -> _addedEntityStore - person mathijsuitmegen; 06.04.2010
comment
Это то, что я делаю, когда работаю в режиме отладки. В моем случае проверка свойств среды выполнения показала, что все данные на месте, все ключи заполнены и корректны. Я думаю, что EF просто не отслеживает вещи на том уровне, на котором можно было бы ожидать. Я торопился, когда публиковал, поэтому просто решил использовать хранимые процедуры для сохранения сложных деревьев сущностей. - person Tim Rourke; 07.04.2010
comment
Привет, я думаю, что у меня проблема, которую вы описываете, о добавлении объектов вместо указания на них (я продолжаю получать новые объекты Country в своей БД, когда я на самом деле пытаюсь ссылаться на них в других объектах..) Как указать объект вместо добавления нового? Кажется, они добавляются, когда я делаю это: CountryRepresentation rep = new CountryRepresentation() { Company = company, Country = MiscRepository.GetCountry(Int32.Parse(country)) };, а затем сохраняю..? - person Niclas Lindqvist; 23.06.2011
comment
Как и выше, используйте метод context.Attach для присоединения ваших объектов к EF. В противном случае вы просто создаете новые. - person Damovisa; 24.06.2011

Я получил эту ошибку, потому что в таблице не было первичного ключа, у нее была ссылка FK, но не PK.

После добавления ПК и обновления модели все хорошо.

person user456649    schedule 23.09.2010

Проверьте, загружен ли ваш ReportSource с параметром NoTracking или его EntityState == 'Detached'. Если это так, это ваша проблема, она должна быть загружена в контексте.

person ADB    schedule 19.08.2009
comment
Спасибо за комментарий. Я уже проверил EntityState в режиме отладки, но не вариант NoTracking. Я попробовал это, вызванное вашим комментарием, без радости. Я также повторно сгенерировал свою модель, чтобы увидеть, не вызвало ли последнее обновление проблему, но это не имело значения. Чтобы обойти это, я просто написал хранимую процедуру для очистки любых связанных объектов и удаления сущности. - person Tim Rourke; 20.08.2009

У меня такая же ошибка из-за нового экземпляра объекта, созданного «за сценой» в состоянии «Добавлено». Это было неочевидно.

person Ratamahatta    schedule 06.04.2010
comment
Это точно не очевидно. В моем случае я пишу инструменты, которые будут поддерживаться другими, и я не мог с чистой совестью оставить такую ​​ситуацию для них, поэтому я разделил задачи на хранимые процедуры для сложных объектов. - person Tim Rourke; 07.04.2010

Я получил эту ошибку, когда добавил новый объект в контекст, но забыл добавить новый объект в его родительскую коллекцию в графе объектов.

Например:

Pet pet = new Pet();
context.Pets.Add(pet);
// forgot this: petOwner.Pets.Add(pet);
person JohnWrensby    schedule 13.10.2016