Lazy Loading is already available. There are two options:
- using proxy objects generated by EF Core to automagically load related entities or
- use the
ILazyLoader service with POCOs to load related entities when requested
Proxies
To use proxies, the DbContext has to be configured first :
.AddDbContext<BloggingContext>( b => b.UseLazyLoadingProxies() .UseSqlServer(myConnectionString));
After that, any properties that need to be lazy loaded have to be made virtual :
public class Blog { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Post> Posts { get; set; } } public class Post { public int Id { get; set; } public string Title { get; set; } public string Content { get; set; } public virtual Blog Blog { get; set; } }
At runtime EF will return proxy objects that inherit from the entity classes and overload the lazy properties to load the related object when first requested.
ILazyLoader service
Another option, that doesn't require inheritance, is to use POCOs and the ILazyLoader service to load the entities when needed :
public class Blog { private ICollection<Post> _posts; public Blog() { } private Blog(ILazyLoader lazyLoader) { LazyLoader = lazyLoader; } private ILazyLoader LazyLoader { get; set; } public int Id { get; set; } public string Name { get; set; } public ICollection<Post> Posts { get => LazyLoader.Load(this, ref _posts); set => _posts = value; } }
This adds a dependency on the ILazyLoader interface itself, which in turn adds a dependency to EF Core in domain or business models.
This can be avoided by injecting the loader as a lambda, along with some convention magic :
public class Blog { private ICollection<Post> _posts; public Blog() { } private Blog(Action<object, string> lazyLoader) { LazyLoader = lazyLoader; } private Action<object, string> LazyLoader { get; set; } public int Id { get; set; } public string Name { get; set; } public ICollection<Post> Posts { get => LazyLoader.Load(this, ref _posts); set => _posts = value; } }
This is used in combination with an extension method that actually calls the loader using the property's name and sets its backing field :
public static class PocoLoadingExtensions { public static TRelated Load<TRelated>( this Action<object, string> loader, object entity, ref TRelated navigationField, [CallerMemberName] string navigationName = null) where TRelated : class { loader?.Invoke(entity, navigationName); return navigationField; } }
As the docs warn:
The constructor parameter for the lazy-loading delegate must be called "lazyLoader". Configuration to use a different name than this is planned for a future release.
Childis null, it means Lazy Loading wasn't enabled and theChildproperty isn'tvirtual.