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] 标记属性表示序列化的时候不进行序列化。