У меня есть модель, в которой с 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?
@IvanStoev контекст полностью загружен заранее (опущен для краткости): ctx.People.Load(); ctx.Keys.Load() - это должно быть как минимум эквивалентно?
Теоретически - да. На практике - кто знает :) В примере "Удаление вручную" отсутствует часть кода до =, что там? Также какая из двух сущностей является зависимой (в какой таблице есть FK)?
@IvanStoev проверил в отладчике, свойство навигации загружено (а поскольку удаление работает, оно должно быть даже без отладки). Key имеет столбец сгенерированного внешнего ключа, Person - нет.
Я не знаю, что сказать - один ко многим также ведет себя аналогичным образом при удалении дочернего элемента из родительской коллекции. Логически это можно рассматривать как удаление, но EF требует, чтобы вы удалили его вручную (Remove из соответствующего DbSet). Думаю, тебе следует жить с таким поведением. И вообще по возможности избегайте однозначных отношений FK в EF6.
Странный. В вашем первом примере я ожидал, что запись Key будет обновлена. Что произойдет, если вы не загрузите данные и не запросите Person с помощью Include(p => p.Key)?
@GertArnold, к сожалению, без изменений





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