zoukankan      html  css  js  c++  java
  • EF中延迟加载的那些事

    延迟加载又称懒加载,通俗一点就是关联了一个对象,不用的时候不去查这个对象,当调用的时候再组织sql去查出这个对象的相关内容。

    一.在使用EF时,我们会发现借助于框架生成的实体类中的的导航属性通常是标记 virtual的,这是为何呢?

     二.让我们通过几个例子来发现其中的奥秘

    下面的代码是通用的查询,先是打印了查询生成的sql,接着查询出一个Employee对象并带出对应的Dempartment对象。

           using (DemoEntities db = new DemoEntities())
                {
                    db.Database.Log = sql => Console.WriteLine(sql);
                    Employee emp = db.Employees.FirstOrDefault();
                    Console.WriteLine(emp.Name);
                    Console.WriteLine(emp.Department.Name);    
                }

       1.导航属性上有virtual的情况下查询两条sql,一条是查出Employee另一条是查Dempartment

     2.现在我们将默认的导航属性中的virtual去掉会发生什么呢,让我们带着疑惑继续往下看

    三.原理探究

    看到这是不是感觉很怪异喽,加上virtual就能正常执行,去掉就不行了么。这是啥原理呢

    1.我们把代码修改一下

         using (DemoEntities db = new DemoEntities())
                {
                    Employee emp = db.Employees.FirstOrDefault();
                    Console.WriteLine(emp.GetType());  //打印emp的类型
                    Console.WriteLine(emp.GetType().BaseType);  //打印emp类型对应的父类
                    Console.WriteLine(emp.Name);
                    Console.WriteLine(emp.Department.Name);
                }

    在原有的基础上我们打印了一下对应对象的类型

    2.我们还是先看看默认有virtual的情况

     通过执行代码我们发现,我们所声明的Employee的对象的类型竟然不是Employee而是一个名字特别长的另一个对象,而这个对象的父类才是Employee

    3.我们将导航属性的virtual去掉再执行代码看看有什么变化

     看到这里的差异,我们似乎发现了点什么。先说说virtual关键字吧,virtual是虚方法,通常是用于子类的重写。那么这里我们不难推测当导航属性有virtual关键字时,EF帮我们生成了一个

    父类是Employee名字老长老长的那个类,在这个类的实现中,重写了一下,当Department为空时,它会去数据库里查一下这个Department对象,所以加上virtual关键字时就会对应两条sql

    类似效果如下所示

        class Employee_515EB7DF3C6168BFE9566BD863543E3AED9398AFF473BAB129D9B32823D6E8A3 : Employee {
                private Department _department;
                public override Department Department
                {
                    get
                    {
                        if (_department==null)
                        {
                            //去数据库中查询Department的信息
                        }
                        return _department;
                    }
                }
            }
  • 相关阅读:
    3.Appium运行时出现:Original error: Android devices must be of API level 17 or higher. Please change your device to Selendroid or upgrade Android on your device
    3.Python连接数据库PyMySQL
    2.Python输入pip命令出现Unknown or unsupported command 'install'问题解决
    2.Linux下安装Jenkins
    5.JMeter测试mysql数据库
    Android 4学习(7):用户界面
    Android 4学习(6):概述
    Android 4学习(5):概述
    Android 4学习(4):概述
    Android 4学习(3):概述
  • 原文地址:https://www.cnblogs.com/HTLucky/p/13335031.html
Copyright © 2011-2022 走看看