Opožděné načítání souvisejících dat
Opožděné načítání s proxy servery
Nejjednodušší způsob, jak používat opožděné načítání, spočívá v instalaci balíčku Microsoft.EntityFrameworkCore.Proxies a povolením volání UseLazyLoadingProxies
. Příklad:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString);
Nebo při použití addDbContext:
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
EF Core pak povolí opožděné načítání pro všechny navigační vlastnosti, které lze přepsat- to znamená, že musí být virtual
a ve třídě, ze které lze dědit. Například v následujících entitách Post.Blog
budou vlastnosti a Blog.Posts
navigace opožděně načteny.
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; }
}
Upozorňující
Opožděné načítání může způsobit výskyt nepotřebných dodatečných cyklů databáze (tzv. problém N+1) a měli byste se tomu vyhnout. Další podrobnosti najdete v části o výkonu.
Opožděné načítání bez proxy serverů
Opožděné načítání bez proxy fungují vložením ILazyLoader
služby do entity, jak je popsáno v konstruktorech typů entit. Příklad:
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;
}
}
Tato metoda nevyžaduje, aby typy entit byly zděděny z vlastností navigace nebo aby byly virtuální, a umožňuje instancím entit vytvořeným new
s opožděným načtením po připojení k kontextu. Vyžaduje však odkaz na ILazyLoader
službu, která je definována v balíčku Microsoft.EntityFrameworkCore.Abstractions . Tento balíček obsahuje minimální sadu typů, aby v závislosti na něm byl malý dopad. Pokud se ale chcete zcela vyhnout v závislosti na jakýchkoli balíčcích EF Core v typech entit, je možné metodu ILazyLoader.Load
vložit jako delegáta. Příklad:
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;
}
}
Výše uvedený kód používá metodu Load
rozšíření, která delegáta trochu čistí:
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;
}
}
Poznámka
Parametr konstruktoru pro opožděný delegát načítání musí být volána "lazyLoader". Konfigurace pro použití jiného názvu, než je naplánováno pro budoucí verzi.