EF之关联加载

一、介绍

Entity Framework作为一个优秀的ORM框架,它使得操作数据库就像操作内存中的数据一样,但是这种抽象是有性能代价的,故鱼和熊掌不能兼得。但是,通过对EF的学习,可以避免不必要的性能损失。本篇只介绍关联实体的加载的相关知识,这在我之前的文章中都有介绍。
我们已经了解到EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延迟加载。
(一)Lazy Loading使用的是动态代理,默认情况下,如果POCO类满足以下两个条件,EF就使用Lazy Loading:
  1. POCO类是Public且不为Sealed。
  2. 导航属性标记为Virtual。
关闭Lazy Loading,可以将LazyLoadingEnabled设为false,如果导航属性没有标记为virtual,Lazy Loading也是不起作用的。
(二)Eager Loading使用Include方法关联预先加载的实体。
(三)Explicit Loading使用Entry方法,对于集合使用Collection,单个实体则使用Reference。


二、实例

下面通过实例来理解这几种加载方式。
有下面三个实体:Class(班级),Student(学生),HeadTeacher(班主任) ,一个Class有多个Student,并且只有一个HeadTeacher 。


public partial class Class
{
    public Class()
    {
        this.Student = new HashSet<Student>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual HeadTeacher HeadTeacher { get; set; }
    public virtual ICollection<Student> Student { get; set; }
}

public partial class HeadTeacher
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public partial class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Lazy Loading
private static void LazyLoading(EFLoadingContext ctx)
{
    //发送一条查询到数据库,查询所有的Class
    var list = ctx.Classes.ToList();
    foreach (var _class in list)
    {
        //每次遍历(用到导航属性时)都发送2条查询,一条查询当前Class包含的Student和另一条查询当前Class的HeadTeacher
        //如果ctx.Configuration.LazyLoadingEnabled为false或者前者为true,但是导航属性没有标注为virtual,下面的操作都会抛出异常
        Print(_class);
    }
}
 
Eager Loading
private static void EagerLoading(EFLoadingContext ctx)
{
    //发送一条查询到数据库库,查询所有的Class并关联Student和HeadTeacher
    var list = ctx.Classes.Include(t => t.Students).Include(t => t.HeadTeacher);
    foreach (var _class in list)
    {
        //不管ctx.Configuration.LazyLoadingEnabled为false,还是没有标注导航属性virtual,都不会抛出异常
        Print(_class);
    }
}
 
Explicti Loading
private static void ExplicitLoading(EFLoadingContext ctx)
{
    //发送一条查询到数据库,查询所有的Class
    var list = ctx.Classes.ToList();
    foreach (var _class in list)
    {
        var p = ctx.Entry(_class);
        //发送一条查询,查询所有当前Class的Student
        p.Collection(t => t.Students).Load();
         //发送一条查询,查询当前Class的HeadTeacher
         p.Reference(t => t.HeadTeacher).Load();
         //不管ctx.Configuration.LazyLoadingEnabled为false,还是没有标注导航属性virtual,都不会抛出异常
         Print(_class);
    }
}
 
Print方法
private static void Print(Class _class)
{
    Console.WriteLine("班级:【{0}】,学生:【{1}】,班主任:【{2}】", _class.Name, string.Join(",", _class.Students.Select(t => t.Name)), _class.HeadTeacher.Name);
}

 三、总结

关于关联加载实体基本上就是这些内容吧,总的来说,这部分比较简单,一个LazyLoadingEnabled设置,三种加载方式。Lazy Loading会生成大量的sql,Eager Loading生成的关联查询比较负责,Explicit Loading同Lazy Loading一样生成很多的sql,但是有一些其他优点,比如:导航属性可以不用标注为virtual。如果这几种关联都不能解决实际问题,可以直接使用sql查询。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值