efcore系列四 加载关联数据的方式

efcore 给出的关联数据加载的方式有三种:Eager Loading、Explicit Loading、Lazy Loading,其实还有一种,下面再说( •̀ ω •́ )。

Eager Loading(预先加载)

还是用上一篇文章创建的实体做下演示

        /// 
        /// EagerLoading
        /// 
        /// 
        public static object StudentEagerLoading()
        {
            using (var dbContext = new AppDbContext())
            {
                //使用Include一次查询出导航属性 StudentCourses
                var student = dbContext.Students.Include(s=>s.StudentCourses)
                                                .FirstOrDefault();

                //StudentCourses集合已经加载
                foreach (var course in student.StudentCourses)
                {
                    Console.WriteLine($"{course.CourseId}");
                }

                return student;
            }
        }

这种加载方式使用起来很方便,尤其是在应对复杂的业务逻辑时。缺点是,预先加载会加载所有数据,包括我们当不需要的那部分。

Explicti Loading(显式加载)

        /// 
        /// 显示加载
        /// 
        /// 
        public static Student StudentExplicitLoading()
        {
            using (var dbContext = new AppDbContext())
            {
                //先查询出student
                var student = dbContext.Students.First();

                //加载StudentCourses 
                dbContext.Entry(student).Collection(s=>s.StudentCourses).Load();

                foreach(var studentCourse in student.StudentCourses)
                {
                    //加载Course
                    dbContext.Entry(studentCourse).Reference(s => s.Course).Load();

                    Console.WriteLine($"{studentCourse.Course.CourseName}");
                }
                return student;
            }
        }

Explicit Loading使用Entry方法,对于集合使用Collection,单个实体使用Reference

Lazy Loading (延迟加载)

Lazy Loading是指在访问导航属性时,才去数据库中加载关联数据,这个过程不需要显式指定加载数据。
Lazy Loading有两种方式实现 推荐第一种引用包 Microsoft.EntityFrameworkCore.Proxies,具体可以参考:https://docs.microsoft.com/zh-cn/ef/core/querying/related-data

开启延迟加载的条件是 导航属性必须设为virtual,并且这个类不是可被继承的(非Sealed)
修改 OnConfiguring方法

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseLazyLoadingProxies().UseMySql(ConnStr);
        }
        /// 
        /// 延迟加载
        /// 
        /// 
        public static Student StudentLazyLoading()
        {
            using (var dbContext = new AppDbContext())
            {
                //先查询出student
                var student = dbContext.Students.First();

                //查出studentCourses
                var studentCourses = student.StudentCourses.ToList();

                foreach(var studentCourse in studentCourses)
                {
                    var course = studentCourse.Course;
                    Console.WriteLine($"{course.CourseName}");
                }

                return student;
            }
        }

最后一种加载关联数据的方式,Select Loading选择加载

选择加载是指从关联的实体中加载只需要的那部分

        /// 
        /// 选择加载
        /// 
        /// 
        public static string StudentSelectLoading()
        {
            using (var dbContext = new AppDbContext())
            {
                var data = dbContext.Students.Select(s => new
                {
                    s.StudentName,
                    s.StudentCourses.First().Course.CourseName
                }).First();

                return JsonConvert.SerializeObject(data);
            }
        }

Json序列化这里需要注意一下循环引用的问题,可以参考https://docs.microsoft.com/zh-cn/ef/core/querying/related-data#related-data-and-serialization解决

你可能感兴趣的:(efcore系列四 加载关联数据的方式)