На мой взгляд, для Entity Framework не имеет смысла загружать всех дочерних элементов только для того, чтобы добавить один
Ленивая загрузка происходит в первый раз, когда вы получаете доступ свойство навигации через его getter .И пример кода
_parent.Children.Add(child);
состоит из двух операций:
(1) получить свойство Children
(через свойство getter !):
var children = _parent.Children;
(2) выполнить с ним некоторую операцию (в этом случае вызвать метод Add
):
children.Add(child);
Из-за операции (1) происходит отложенная загрузка.Как видите, EF не имеет к этому никакого отношения, потому что не контролирует его.И нет никакого способа узнать, что вы собираетесь делать со значением этого свойства - перечислите его, проведите подсчет или используйте методы Add
, Remove
и т. Д.
Вот несколько решений.
Во-первых, зачем вообще ленивая загрузка?У него так много побочных эффектов и неэффективностей, и все они могут быть легко решены с помощью EF, предоставляемой из готовой к загрузке системы методами Include
.Вот почему по умолчанию EF Core («будущее EF») не использует отложенную загрузку по умолчанию и требует специального пакета и процедуры для его включения.
Во-вторых, если вы настаиваете на использовании отложенной загрузки, то у вас естьследующие две опции:
(A) Отключить отложенную загрузку во время изменения данных (требуется доступ к / управление экземпляром DbContext
):
dbContext.Configuration.LazyLoadingEnabled = false;
_parent.Children.Add(child);
dbContext.Configuration.LazyLoadingEnabled = true;
Для этого также требуется свойство коллекциибыть инициализированным во избежание NRE.
(B) Используйте явное поле поддержки и предоставьте некоторый прямой доступ к нему (чтобы не вызывать ленивую загрузку с помощью средства доступа к свойству).Например:
public class Parent
{
public Guid Id { get; set; }
private ICollection<Child> children;
public virtual ICollection<Child> Children { get => children; set => children = value; }
public void Add(Child child)
{
// use the backing field directly
if (children == null) children = new HashSet<Child>();
children.Add(child);
}
}