Caricamento differita dei dati correlati
Il modo più semplice per usare il caricamento lazy consiste nell'installare il pacchetto Microsoft.EntityFrameworkCore.Proxies e abilitarlo con una chiamata a UseLazyLoadingProxies
. Ad esempio:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString);
O quando si usa AddDbContext:
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
EF Core abiliterà quindi il caricamento lazy per qualsiasi proprietà di navigazione che può essere sottoposta a override, ovvero deve essere virtual
e in una classe ereditabile. Ad esempio, nelle entità seguenti, le proprietà di navigazione Post.Blog
e Blog.Posts
vengono caricate in modalità lazy.
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; }
}
Avviso
Il caricamento differita può causare l'esecuzione di round trip aggiuntivi aggiuntivi del database (il cosiddetto problema N+1) e prestare attenzione per evitare questo problema. Per altri dettagli, vedere la sezione relativa alle prestazioni.
Il caricamento differita senza proxy funziona inserendo il servizio in un'entità ILazyLoader
, come descritto in Costruttori di tipi di entità. Ad esempio:
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;
}
}
Questo metodo non richiede che i tipi di entità vengano ereditati da o le proprietà di navigazione siano virtuali e consentano alle istanze di entità create con new
il caricamento differita una volta collegati a un contesto. Tuttavia, è necessario un riferimento al servizio ILazyLoader
, che viene definito nel pacchetto Microsoft.EntityFrameworkCore.Abstractions. Questo pacchetto contiene un set minimo di tipi in modo da avere un impatto minimo a seconda di esso. Tuttavia, per evitare completamente a seconda di qualsiasi pacchetto EF Core nei tipi di entità, è possibile inserire il ILazyLoader.Load
metodo come delegato. Ad esempio:
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;
}
}
Il codice precedente usa un metodo di estensione Load
per chiarire l'uso del delegato:
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;
}
}
Nota
Il parametro del costruttore per il delegato di caricamento lazy deve essere chiamato "lazyLoader". La possibilità di configurare l'uso di un nome diverso è pianificata per una versione futura.
Feedback su .NET
.NET è un progetto di open source. Selezionare un collegamento per fornire feedback: