EntityFramework Core延迟加载(LazyLoad)

1、延迟加载介绍

延迟加载又叫惰性加载(Lazy Loading):即在需要或者使用的时候加载数据。

此功能是在EF Core 2.1中引入的。

2、使用延迟加载

2.1 使用 Microsoft.EntityFrameworkCore.Proxies

直接重写OnConfiguring方法配置UseLazyLoadingProxies()

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLazyLoadingProxies()
        .UseSqlServer(myConnectionString);

或者在Configing方法中添加

services.AddDbContext<UserContext>(
    b => b.UseLazyLoadingProxies()
          .UseSqlServer(connectionString));

2.2使用ILazyLoader注入到构造中

  • 定义实体,并构造注入ILazyLoader
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;
    }
}
注意:构造注入的方法是私有的,因为ILazyLoader只和EFCore进行耦合。

2.3使用Action<object, string>让上面的ILazyLoader解耦

  • 使用注入委托的方式进行解耦

    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;
        }
    }
    
  • 扩展Load方法

    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;
        }
    }
    

3、处理序列化时的循环依赖

添加AddJsonOptions
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );
}

或者使用 [JsonIgnore] 标记属性表示序列化的时候不进行序列化。

原文地址:https://www.cnblogs.com/cqxhl/p/12993293.html