C# EF框架(二)延迟加载

本文详细探讨了C# EF框架中的延迟加载(LazyLoad)机制,解释了启用延迟加载的条件及其优缺点。同时,介绍了如何通过Include()方法一次性加载关联数据。还讨论了实体类继承、Linq的使用、C#6.0新语法以及ORM的工作原理和优缺点。
摘要由CSDN通过智能技术生成

目录

延迟加载(LazyLoad)

不延迟加载,怎么样一次性加

延迟加载的一些坑

实体类的继承

linq

简介

辟谣

Linq 基本语法

混用

C#6.0 语法

ORM

ORM简介

ORM的工作原理

ORM的优缺点


延迟加载(LazyLoad)

如果public virtual Class Class { get; set; }(实体之间的关联属性又叫做“导航属性(Navigation Property)”)把virtual 去掉,那么下面的代码就会报空引用异常

var s = ctx.Students.First();
Console.WriteLine(s.Class.Name);

联想为什么?凭什么!!! 改成virtual观察SQL的执行。执行了两个SQL,先查询T_Students,再到T_Classes中查到对应的行。 这叫“延迟加载”(LazyLoad),只有用到关联的对象的数据,才会再去执行select 查询。注意延迟加载只在关联对象属性上,普通属性没这个东西。 注意:启用延迟加载需要配置如下两个属性(默认就是true,因此不需要去配置,只要别手贱设置为false 即可)

context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;

分析延迟加载的原理:打印一下拿到的对象的GetType(),再打印一下GetType().BaseType;我们发现拿到的对象其实是Student子类的对象。(如果和我这里结果不一致的话,说明:类不是public,没有关联的virtual 属性) 因此EF其实是动态生成了实体类对象的子类,然后override了这些virtual属性,类似于这样的 实现:

public class StudentProxy:Student
{
    private Class clz;
    public override Class Class
    {
        get
        {
            if(this.clz==null)
            {
                this.clz= ....//这里是从数据库中加载Class 对象的代码
            }
            return this.clz;
        }
     }
}

再次强调:如果要使用延迟加载,类必须是public,关联属性必须是virtual。 延迟加载(LazyLoad)的优点:用到的时候才加载,没用到的时候才加载,因此避免了一次性加载所有数据,提高了加载的速度。缺点:如果不用延迟加载,就可以一次数据库查询就可以把所有数据都取出来(使用join实现),用了延迟加载就要多次执行数据库操作,提高了数据库服务器的压力。 因此:如果关联的属性几乎都要读取到,那么就不要用延迟加载;如果关联的属性只有较小的概率(比如年龄大于7 岁的学生显示班级名字,否则就不显示)则可以启用延迟加载。这个概率到底是多少是没有一个固定的值,和数据、业务、技术架构的特点都有关系,这是需要经验和直觉,也需要测试和平衡的。 注意:启用延迟加载的时候拿到的对象是动态生成类的对象,是不可序列化的,因此不能直接放到进程外Session、Redis 等中,解决方法?

不延迟加载,怎么样一次性加

用EF永远都要把导航属性设置为virtual。又想方便(必须是virtual)又想效率高!

使用Include()方法:

var s = ctx.Students.Include("Class").First();

观察生成的SQL语句,会发现只执行一个使用join的SQL就把所有用到的数据取出来了。当然拿到的对象还是Student 的子类对象,但是不会延迟加载。(不用研究“怎么让他返回Student 对象”)

Include("Class")的意思是直接加载Student 的Class 属性的数据。注意只有关联的对象属性才可以用Include,普通字段不可以直接写"Class"可能拼写错误,如果用C#6.0,可以使用nameof语法解决问这个问题:

var s = ctx.Students.Include(nameof(Student.Class)).First();

也可以using System.Data.Entity;然后var s = ctx.Students.Include(e=>e.Class).First(); 推荐这种做法。 如果有多个属性需要一次性加载,也可以写多个Include:

var s = ctx.Students.Include(e=>e.Class) .Include(e=>e.Teacher).First();

如果Class对象还有一个School属性,也想把School对象的属性也加载,就要:

var s = ctx.Students.Include("Class").Include("Class. School").First(); 或者更好的
var s = ctx.Students.Include(nameof(Student.Class)).Include(nameof(Student.Class)+"."+nameof(Class.School)).First();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值