Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Carregamento preguiçoso com proxies
A forma mais simples de usar o lazy-loading é instalar o pacote Microsoft.EntityFrameworkCore.Proxies e habilitá-lo com uma chamada para UseLazyLoadingProxies. Por exemplo:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString);
Ou ao usar o AddDbContext:
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
EF Core irá então ativar o carregamento preguiçoso para qualquer propriedade de navegação que possa ser substituída — ou seja, deve estar virtual numa classe que possa ser herdada. Por exemplo, nas seguintes entidades, as Post.Blog e Blog.Posts propriedades de navegação serão carregadas de forma preguiçosa.
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; }
}
Advertência
O carregamento preguiçoso pode causar viagens extra desnecessárias de ida e volta à base de dados (o chamado problema N+1), e deve-se ter cuidado para evitar isso. Consulte a secção de atuações para mais detalhes.
Carregamento preguiçoso sem proxies
O carregamento preguiçoso sem proxies funciona ao injetar o serviço ILazyLoader numa entidade, conforme descrito em Construtores de Tipos de Entidade. Por exemplo:
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;
}
}
public class Post
{
private Blog _blog;
public Post()
{
}
private Post(ILazyLoader lazyLoader)
{
LazyLoader = lazyLoader;
}
private ILazyLoader LazyLoader { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog
{
get => LazyLoader.Load(this, ref _blog);
set => _blog = value;
}
}
Este método não exige que os tipos de entidade sejam herdados nem que as propriedades de navegação sejam virtuais, e permite que instâncias de entidade criadas com new carreguem preguiçosamente uma vez anexadas a um contexto. No entanto, requer uma referência ao ILazyLoader serviço, que está definido no pacote Microsoft.EntityFrameworkCore.Abstractions. Este pacote contém um conjunto mínimo de tipos para que haja pouco impacto em depender dele. No entanto, para evitar completamente depender de quaisquer pacotes EF Core nos tipos de entidades, é possível injetar o método ILazyLoader.Load como delegado. Por exemplo:
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;
}
}
public class Post
{
private Blog _blog;
public Post()
{
}
private Post(Action<object, string> lazyLoader)
{
LazyLoader = lazyLoader;
}
private Action<object, string> LazyLoader { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog
{
get => LazyLoader.Load(this, ref _blog);
set => _blog = value;
}
}
O código acima usa um Load método de extensão para tornar o uso do delegado um pouco mais limpo:
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;
}
}
Observação
O parâmetro construtor para o delegado de carregamento preguiçoso deve ser chamado "lazyLoader". Está planeada uma configuração para usar um nome diferente deste para uma versão futura.