EF6中如何让BookModel自动加载关联ICollection,无需重复使用Include?
EF6 自动加载关联集合,避免重复编写Include
我目前使用EF6,BookModel包含多个ICollection类型的关联属性,现在每次获取IEnumerable<BookModel>都要重复写一堆Include:
IEnumerable<BookModel> GetAllBook = DBContext.BookModels.Include(x => x.AssociatedNames).Include(e => e.BlogModel);
重复编写十分繁琐,想知道有没有办法让BookModel自动拥有完整的关联对象列表,无需每次都使用Include?
BookModel定义如下:
public class BookModel { [Key] public int BookModelID{ get; set; } public virtual ICollection<AssociatedNames>? AssociatedNames { get; set; } public virtual List<BookModel>? relatedSeries { get; set; } public virtual List<BookModel>? RecommendedBookModels { get; set; } public virtual ICollection<AuthorModel>? Authormodels { get; set; } public virtual ICollection<ArtistModel>? ArtistModels { get; set; } public virtual ICollection<VoiceActorModel>? VoiceActors { get; set; } public virtual ICollection<GenresModel>? GenresModels { get; set; } public virtual ICollection<TagModel>? TagsModels { get; set; } }
可行解决方案
利用延迟加载(默认开启)
EF6默认启用延迟加载,你的模型关联属性已经标记了virtual关键字,理论上在访问这些属性时,EF会自动从数据库加载关联数据。但要注意两个问题:- 必须保证
DbContext在访问属性时未被释放,否则会抛出异常 - 延迟加载会引发N+1查询问题,数据量较大时会严重影响性能
- 必须保证
在DbContext中封装查询方法
如果需要立即加载所有关联对象,最直接的方式是在DbContext里封装一个预定义好所有Include的方法:
public IQueryable<BookModel> GetBooksWithAllAssociations() { return BookModels .Include(x => x.AssociatedNames) .Include(x => x.relatedSeries) .Include(x => x.RecommendedBookModels) .Include(x => x.Authormodels) .Include(x => x.ArtistModels) .Include(x => x.VoiceActors) .Include(x => x.GenresModels) .Include(x => x.TagsModels); }
之后只需调用DBContext.GetBooksWithAllAssociations(),就能直接获取带全量关联的BookModel集合,无需重复编写Include。
- 初始化集合避免空引用
虽然不能自动加载数据,但可以在BookModel的构造函数里初始化所有集合属性,避免访问时出现NullReferenceException:
public class BookModel { [Key] public int BookModelID{ get; set; } public virtual ICollection<AssociatedNames>? AssociatedNames { get; set; } public virtual List<BookModel>? relatedSeries { get; set; } public virtual List<BookModel>? RecommendedBookModels { get; set; } public virtual ICollection<AuthorModel>? Authormodels { get; set; } public virtual ICollection<ArtistModel>? ArtistModels { get; set; } public virtual ICollection<VoiceActorModel>? VoiceActors { get; set; } public virtual ICollection<GenresModel>? GenresModels { get; set; } public virtual ICollection<TagModel>? TagsModels { get; set; } public BookModel() { AssociatedNames = new HashSet<AssociatedNames>(); relatedSeries = new List<BookModel>(); RecommendedBookModels = new List<BookModel>(); Authormodels = new HashSet<AuthorModel>(); ArtistModels = new HashSet<ArtistModel>(); VoiceActors = new HashSet<VoiceActorModel>(); GenresModels = new HashSet<GenresModel>(); TagsModels = new HashSet<TagModel>(); } }
注意:EF6没有EF Core中的全局查询过滤器功能,无法强制所有查询自动包含关联对象,上述封装查询方法是EF6场景下最实用的解决方案。
内容的提问来源于stack exchange,提问作者Rojhat
相关产品推荐
相关产品推荐

