Эта разница в поведении является следствием долгоживущих DbContexts. Объявив новый DbContext в методе, вы никогда не увидите обновленную ссылку EditorSetting, установив на объекте EditorSettingId FK и сохранив его.
Когда вы используете более длительный DbContext, вы можете см. Обновленный при условии, что DBContext знает об этом. (Ссылка EditorSetting является отслеживаемой сущностью в DbContext)
Например:
Предполагается, что у нас есть сущность Parent и Child. Родитель содержит коллекцию дочерних элементов, а дочерний элемент содержит FK ParentId и свойство виртуальной родительской навигации. Родительский идентификатор # 1 существует в базе данных:
using (var context = new TestDbContext())
{
var newChild = new Child { Name = "Freddy", BirthDate = new DateTime(1999, 3, 3), ParentId = 1 };
context.Children.Add(newChild);
context.SaveChanges();
}
Теперь на этом этапе после SaveChanges
, если вы посмотрите ссылку Parent
для newChild, это будет #null. Вместо этого, если вы сделаете это:
using (var context = new TestDbContext())
{
var neverUsedParent = context.Parents.Single(x => x.ParentId == 1);
var newChild = new Child { Name = "Freddy", BirthDate = new DateTime(1999, 3, 3), ParentId = 1 };
context.Children.Add(newChild);
context.SaveChanges();
}
В этом примере после изменений сохранения вы увидите, что присутствует ссылка «Родитель», даже если мы ее не связывали, мы все равно только установили идентификатор.
Когда у вас есть долгоживущий DbContext, неизбежно может произойти разница в поведении при установке свойств FK, и это может иметь действительно странные последствия, которые обнаруживаются во время выполнения. Если один из EditorSettings был ранее загружен из БД этим DbContext, создание новой записи с этим EditorSettingId заполнит ассоциацию, в то время как другой EditorSettingId этого не сделает. (Поскольку DbContext не знал об этом) Возможно, что EditorSetting был загружен в любом месте кода до этого вызова, при условии, что использовался тот же экземпляр DbContext.
Даже при этом:
using (var context = new TestDbContext())
{
var newChild = new Child { Name = "Freddy", BirthDate = new DateTime(1999, 3, 3), ParentId = 1 };
context.Children.Add(newChild);
context.SaveChanges();
// newChild.Parent == #null here....
var neverUsedParent = context.Parents.Single(x => x.ParentId == 1);
// newChild.Parent is available here!
}
В общем, лучше избегать отображения как навигационных свойств, так и FK. Я советую юридическим лицам использовать один или другой. При использовании свойств навигации вы можете отобразить FK без свойств, используя Shadow Properties в EF Core или Map.MapKey()
в EF 6. В тех случаях, когда я хочу загружать / манипулировать большими объемами данных и не нуждаюсь в соответствующих деталях, я буду использовать FK с в этих объектах нет свойств навигации.