EF延迟加载:就是使用Lamabda表达式或者Linq 从 EF实体对象中查询数据时,EF并不是直接将数据查询出来,而是在用到具体数据的时候才会加载到内存。
一、本质
2、按需加载
二、实现方式
先来介绍几个概念:
概念一:EntityFramework的由来
用过EF的人都知道,我们的程序中都会引用它。它是微软自带的吗?如果是,为什么不直接封装在framework中,而是需要去引用;如果不是,那为什么会创建EF模型时自动创建它。
解释:EntityFramework在创建EF模型中,自动复制,是扩展出来的,用时复制过来,相当于微软开发的第三方程序集,不属于framework
为什么不放在framework中?
老版本中不存在EF,新版本才有EF.为了兼容,现在老版本只需要将其引入即可,不需要重新改动。
概念二:标准查询运算符中的Where含义
(1)普通集合中的Where子句
(2)EF中DbSet返回集合的Where子句
//集合的标准查询运算符方法,是来自于System.Linq.Enumerable里给IEnumerable接口添加的扩展方法(即时)
List<string> listStr = new List<string>();
listStr.Where(i=>listStr.Contains(i));
//上下文中dbSet返回的集合(延时)
List<Order_Info> order = db.Order_Info.Where(u => u.OrderID == 1).ToList();
区别:
普通集合的标准查询运算符方法,来自于system.linq. Enumerable 里的扩展方法,给 IEnumerable 接口添加扩展方法,
IQueryable接口
是非常特殊,正是因为这个接口,才支持的延迟查询,dbset实现iqueryable接口
1、延迟生成SQL语
//延迟查询
DbQuery<Order_Info> i = db.Order_Info.Where(u => u.OrderID == 1) as DbQuery<Order_Info>;
Order_Info order1 = i.FirstOrDefault();
Console.WriteLine();
在这里我们为什么要使用DbQuery<T>来接收呢?
首先我们来看使用db.Order_Info.Where()来获取文章列表的时候,Where()方法给我们返回一个什么类型的对象呢?我们把鼠标放在Where()方法上后,会发现Where会返回给我们一个IQueryable的泛型接口对象,如下图:
那我们是不是需要使用IQueryable对象来接收获取的对象呢,代码如下
//where()方法返回一个IQuery的接口
IQueryable <Order_Info> query= db.Order_Info.Where(p => p.orderID=1);
可以看到query已经取到值,但根据面向对象的原则,接口不能直接实例化,但我们的代码有没有报错,为社么呢?
根据面向对象的里氏替换原则,这里实际上是返回了一个IQueryable对象的子类对象。
里氏替换原则,子类对象可以赋值给父类对象。也就是说子类可以替换父类出现的地方。但是父类对象一定不可以替换子类对象。
也就是说Where()方法返回了一个IQueryable接口的子类对象,并且赋值给了它的父类对象IQueryable。
那么Where()到底返回了一个什么样的IQueryable的子类对象呢?
再次看上面的局变量窗口中query的返回值类型为,如下图:
我们可以很明显的看出,query的返回类型为DbQuery类型。
那我们就用DbQuery来接收对象,代码如下:
DbQuery<Order_Info> i = db.Order_Info.Where(u => u.OrderID == 1) as DbQuery<Order_Info>;
因为Where()方法返回的是IQueryable对象,所以要把对象转换成DbQuery对象;
查询订单表中订单1的创建日期
执行第一条语句:DbQuery<Order_Info> query = db.Order_Info;
执行第二条语句:Order_Info order = query.FirstOrDefault();
我们只是用到订单信息时,才去数据库查询第一条订单的信息
2、按需加载
EF使用前:当遇到主外键相互关联的表,当需要从表中的数据时,我们必须通过主表进行查询。而我们只是需要从表数据,而必须关联到主表。这种方式是低效的。
EF使用后:我们只需要查询数从表的数据即可
查询订单表中产品1的相关信息
三、好处
1、生成一条语句(用的时候,根据条件拼成sql语句)
2、不受主表约束,提高效率
情况1:是针对产品表中的数据进行检索再排序
db.Order_Detail.Where(u => u.OrderID == 1).OrderBy(u=>u.ProductID)
情况2:是针对检索出来的list集合进行排序
db.Order_Detail.Where(u => u.OrderID == 1).ToList().OrderBy(u=>u.ProductID)
情况1为延时查询,根据拼出的SQL语句进行查询;情况2为即时查询。
以上只是只是简单的介绍EF的延迟加载,文中还有很多需要在学习过程中进一步完善,下篇博文会对延迟加载的优化进行深入阐述
步步深入EF(三)—优化延迟加载