Настройка EF от 1 до 0..1 Свойство навигации вызывает исключение

У меня есть модель, в которой с Personможет связан Key, а с Keyдолжен есть Person (каскад), смоделированный следующей моделью с первым кодом со свойствами навигации:

class Key {
  [Key]
  public string Code { get; set; }
  [Required]
  public virtual Person Person { get; set; }
}

class Person {
  [Key]
  public int ID { get; set; }
  public virtual Key Key { get; set; }
}

однако, когда есть сущность Person с Key, замена Key на другую вызывает исключение:

Person person = ctx.People.First(); //ctx loaded with ctx.People.Load(); ctx.Keys.Load()
person.Key = new Key () { Code = "Foo" };
ctx.SaveChanges(); //<---exception thrown

с сообщением:

A relationship from the 'Key_Person' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'Key_Person_Source' must also in the 'Deleted' state.

что не имеет смысла: Key находится в удаленном состоянии (первое предложение)? Хорошо. Я хочу чтобы. Но почему его нельзя заменить другим Key или удалить, если есть атрибут [Required], я не понимаю (второе предложение).
Удаление текущего Key вручную работает:

Person person = ctx.People.First();
if (person.Key != null) ctx.Keys.Remove(person.Key);//<---manually update
person.Key = new Key () { Code = "Foo" };
ctx.SaveChanges(); //<---no exception

Но разве это не должно быть причиной использования свойств навигации, в первую очередь избегая ручного обновления DBSets?

Это может быть связано с изменением отслеживания EF и отложенной загрузки (и ограниченной поддержки EF для этого типа отношений). Вы пробовали var person = ctx.People.Include(p => p.Key); до модификации Key?

Ivan Stoev 23.07.2018 11:17

@IvanStoev контекст полностью загружен заранее (опущен для краткости): ctx.People.Load(); ctx.Keys.Load() - это должно быть как минимум эквивалентно?

wondra 23.07.2018 11:23

Теоретически - да. На практике - кто знает :) В примере "Удаление вручную" отсутствует часть кода до =, что там? Также какая из двух сущностей является зависимой (в какой таблице есть FK)?

Ivan Stoev 23.07.2018 12:16

@IvanStoev проверил в отладчике, свойство навигации загружено (а поскольку удаление работает, оно должно быть даже без отладки). Key имеет столбец сгенерированного внешнего ключа, Person - нет.

wondra 23.07.2018 13:07

Я не знаю, что сказать - один ко многим также ведет себя аналогичным образом при удалении дочернего элемента из родительской коллекции. Логически это можно рассматривать как удаление, но EF требует, чтобы вы удалили его вручную (Remove из соответствующего DbSet). Думаю, тебе следует жить с таким поведением. И вообще по возможности избегайте однозначных отношений FK в EF6.

Ivan Stoev 23.07.2018 13:42

Странный. В вашем первом примере я ожидал, что запись Key будет обновлена. Что произойдет, если вы не загрузите данные и не запросите Person с помощью Include(p => p.Key)?

Gert Arnold 23.07.2018 17:13

@GertArnold, к сожалению, без изменений

wondra 24.07.2018 14:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
94
0

Другие вопросы по теме