ASP.NET EF 延迟加载,导航属性延迟加载

 

EF(EntityFramework)原理:属于ORM的一种实现

通过edmx文件来查看三部分:概念模型,数据模型,映射关系,上下文DbContext完成连接、状态跟踪管理,核心类是EntityClient完成映射

EF(EntityFramework)延迟加载:

>1:EF查询默认会延迟加载

>2:EF对于集合类型的导航属性会延迟加载

本质:IQueryable拥有3个成员,Expression,Type,Provider

IQueryable与IEnumberable对比区别:

IQueryable: 可以拼接一个完成的SQL语句,然后请求数据库,拿到需要的数据

IEnumberable:直接把第一个命令请求数据库,然后拿到数据,在内存当中对于后续条件进行筛选。

把IQueryable 转换为IEnumberable :IQueryable.AsEnumberable();

EF非延迟加载:使用ToList()方法将结果立即拿到内存中(最好把命令全部拼接完之后使用ToList())

EF导航属性的非延迟加载Include("") 可以使导航属性非延迟加载

EF延迟加载 优点:用时才加载数据,保证数据的有效性

EF延迟加载 缺点:每次访问都加载一次,加重了数据库服务器的负担

个人补充:

绝大部分标准的LINQ查询运算符都具有延迟加载这种特性,但也有例外:

  •  那些返回单个元素或返回一个数值的运算符,如First或Count。
  • 转换运算符:ToArray,ToList,ToDictonnary,ToLookup。

以上这些运算符都会触发LINQ语句立即执行,因为它们的返回值类型不支持延迟加载。

create database MyFirstEF
on primary
(
name='MyFirstEF.mdf',
--修改为自己电脑上SQL DB路径
filename='E:\ProgramMSSQLServerDB\MyFirstEF.mdf',
size=5mb,
maxsize=100mb,
filegrowth=10%
)
log on
(
name='MyFirstEF_log.ldf',
--修改为自己电脑上SQL DB路径
filename='E:\ProgramMSSQLServerDB\MyFirstEF_log.ldf',
size=2mb,
maxsize=100mb,
filegrowth=5mb
)
go use MyFirstEF
go create table CustomerInfo
(
id int identity(1,1) primary key,
customerName nvarchar(100) not null,
customerDate datetime
)
go create table OrderInfo
(
id int identity(1,1) primary key,
orderName nvarchar(100),
customerId int
)
go alter table OrderInfo
add constraint FK_OrderInfo_CustomerInfo foreign key(customerId) references CustomerInfo(id)
go insert into CustomerInfo
select 'aa',GETDATE() union all
select 'bb',GETDATE() union all
select 'cc',GETDATE() union all
select 'dd',GETDATE()
go insert into OrderInfo
select 'bike1',2 union all
select 'bike2',2 union all
select 'car1',3 union all
select 'car2',3 union all
select 'chezi1',4 union all
select 'chezi2',4
go select * from CustomerInfo
go select * from OrderInfo
go

>1:EF查询默认会延迟加载

DbContext context = new MyFirstEFEntities();
//1:EF默认延迟加载,执行完下面的语句,数据库并没有SQL查询语句
var rows = context.Set<CustomerInfo>().Select(c => c);
//2:查询一次数据库
Console.WriteLine(rows.Count());
//3:第二次查询数据库
Console.WriteLine(rows.Count());

使用MS SQL Server Profiler(工具-->SQL Server Profiler),可以监测到上面代码执行了两次查询数据库操作

两次查询数据库SQL:

SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[CustomerInfo] AS [Extent1]
) AS [GroupBy1]

>EF非延迟加载:ToList()方法

DbContext context = new MyFirstEFEntities();
//1:直接根据拼接SQL 查询数据库
var rows = context.Set<CustomerInfo>().Select(c => c).ToList(); //2:在内存中统计Count() 不会重新查询数据库
Console.WriteLine(rows.Count());
//3:在内存中统计Count() 不会重新查询数据库
Console.WriteLine(rows.Count());

使用MS SQL Server Profiler(工具-->SQL Server Profiler),可以监测到上面代码在拼接SQL完成时,直接查询数据库

对应SQL:

SELECT
[Extent1].[id] AS [id],
[Extent1].[customerName] AS [customerName],
[Extent1].[customerDate] AS [customerDate]
FROM [dbo].[CustomerInfo] AS [Extent1]

 >2:EF对于集合类型的导航属性会延迟加载

DbContext context = new MyFirstEFEntities();
//1:EF默认延迟加载,执行完下面的语句,数据库并没有SQL查询语句
var rows = context.Set<CustomerInfo>().Select(c => c);
//2:第一次查询数据库,查询CustomerInfo表
foreach (var row in rows)
{
//foreach时 这个会执行多次 每次@EntityKeyValue1 等于 迭代到这次的 OrderInfoId
Console.WriteLine(row.OrderInfoes.Count);
}

使用MS SQL Server Profiler(工具-->SQL Server Profiler),可以监测到执行到foreach时,执行CustomerInfo表格数据的查询(即为:EF查询默认会延迟加载)

此时对应SQL为:

SELECT
[Extent1].[id] AS [id],
[Extent1].[customerName] AS [customerName],
[Extent1].[customerDate] AS [customerDate]
FROM [dbo].[CustomerInfo] AS [Extent1]

foreach循环时  这个会执行多次  每次@EntityKeyValue1 等于 迭代到这次的 OrderInfoId,对应SQL为:

exec sp_executesql N'SELECT
[Extent1].[id] AS [id],
[Extent1].[orderName] AS [orderName],
[Extent1].[customerId] AS [customerId]
FROM [dbo].[OrderInfo] AS [Extent1]
WHERE [Extent1].[customerId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1

用MS SQL Server Profiler(工具-->SQL Server Profiler),可以监测到执行到foreach时 执行了4次数据库查询(rows有4条CustomerInfo数据)

//也就是说 我们有多少条OrderInfo 就要执行多少次上面的查询SQL   当然 这里使用的是exec sp_executesql   利用sp_executesql,能够重用执行计划,这就大大提供了执行性能

 >EF导航属性的非延迟加载: Include("")方法

DbContext context = new MyFirstEFEntities();
//1:EF默认延迟加载,执行完下面的语句,数据库并没有SQL查询语句
var rows = context.Set<CustomerInfo>().Include(c=>c.OrderInfoes).Select(c => c);
//2:第一次查询数据库,查询CustomerInfo表,以及CustomerInfo对应的所有OrderInfo数据
foreach (var row in rows)
{
//foreach时,不会执行数据库查询操作
Console.WriteLine(row.OrderInfoes.Count);
}

使用MS SQL Server Profiler(工具-->SQL Server Profiler),可以监测到执行foreach时,执行CustomerInfo表格数据的查询(EF查询默认会延迟加载),以及CustomerInfo对应的所有OrderInfo数据(EF导航属性的非延迟加载)

对应SQL为:

SELECT
[Project1].[id] AS [id],
[Project1].[customerName] AS [customerName],
[Project1].[customerDate] AS [customerDate],
[Project1].[C1] AS [C1],
[Project1].[id1] AS [id1],
[Project1].[orderName] AS [orderName],
[Project1].[customerId] AS [customerId]
FROM ( SELECT
[Extent1].[id] AS [id],
[Extent1].[customerName] AS [customerName],
[Extent1].[customerDate] AS [customerDate],
[Extent2].[id] AS [id1],
[Extent2].[orderName] AS [orderName],
[Extent2].[customerId] AS [customerId],
CASE WHEN ([Extent2].[id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM [dbo].[CustomerInfo] AS [Extent1]
LEFT OUTER JOIN [dbo].[OrderInfo] AS [Extent2] ON [Extent1].[id] = [Extent2].[customerId]
) AS [Project1]
ORDER BY [Project1].[id] ASC, [Project1].[C1] ASC

关闭延迟加载的方式:

1.去掉属性里的virtual

2.context.Configuration.LazyLoadingEnabled = false;

重要理解点:

1.延迟加载将查询的转换和查询的执行进行了解耦,查询条件紧紧是对输入集合重新进行了筛选,保留那些符合条件的元素指针引用。

本文转载自:http://www.cnblogs.com/DrHao/p/5365325.html

其他关于延迟加载的介绍:

http://www.cnblogs.com/visibleisfalse/p/4973593.html

http://www.cnblogs.com/czx1/p/4947855.html

ASP.NET EF 延迟加载,导航属性延迟加载的更多相关文章

  1. 【ASP.NET Core】EF Core - “导航属性”

    “导航属性”是实体框架用得算是比较频繁的概念. 首先,它是类型成员,其次,他是属性,这不是 F 话,而是明确它的本质.那么,什么场景下会用到导航属性呢?重点就落在“导航”一词上了,当实体 A 需要引用 ...

  2. MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式

    文章索引和简介 通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种 ...

  3. CodeFirst EF中导航属性的个人理解

    >导航属性: 01.个人理解就是Ef中的属性在实体数据表中不存在(先这么认为); 02.就是除了根据表中列映射出的属性 之外根据表与表之间的关系的关联属性.方便操作与之关联的表; 例如: 有 表 ...

  4. EF通过导航属性取出从表的集合后,无法删除子表

    主从表是配了级联删除的,如果通过导航属性去除从表明细删除时将报错The relationship could not be changed because one or more of the for ...

  5. EF的导航属性

    在EF中,外键被称为导航属性. 在EF core中,查询的时候默认是只查自身而不会去查询外键表的.如果想要让查询结果包含外键实体,则需要使用include方法来让查询结果包含外键实体.如 db.Stu ...

  6. C# 数据操作系列 - 7. EF Core 导航属性配置

    在上一篇,大概介绍了Entity Framework Core关于关系映射的逻辑.在上一篇中留下了EF的外键映射没有说,也就是一对一,一对多,多对一,多对多的关系等.这一篇将为大家细细分析一下,如何设 ...

  7. ef 更新导航属性

    总之,要让所有的东西,都被DbContext管理状态 1.查出来,改了,再提交 2.new 出来,attach,再改,再提交 以上两种都较好理解 3.new出来,改了,再attach,在改状态,再提交 ...

  8. Entity Framework应用:导航属性

    一.主键和外键 关系型数据库中的一条记录中有若干个属性,若其中某一个属性组是能唯一标识一条记录,该属性组就可以称为主键.例如: 学生版(学号.姓名.性别.班级) 其中每个学生的学号是唯一的,学号就是一 ...

  9. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

随机推荐

  1. 【洛谷P1896】互不侵犯

    题目大意:给定 N*N 的棋盘,一共放 K 个国王,一共有多少种方法. 题解: i&i<<1 判断是否每个 1 的位置之间都有 0. i&j<<1 判断 i 中 ...

  2. Vue中data返回对象和返回值的区别

    速记:粗浅的理解是,事件的结果是影响单个组件还是多个组件.因为大部分组件是要共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象 返回对象的时候 <!DOCTYPE ...

  3. 使用webdriver+urllib爬取网页数据(模拟登陆,过验证码)

    urilib是python的标准库,当我们使用Python爬取网页数据时,往往用的是urllib模块,通过调用urllib模块的urlopen(url)方法返回网页对象,并使用read()方法获得ur ...

  4. JS学习笔记Day2

    一.程序的三大结构 顺序结构:从上到下,从左到右依次执行每一条语句 选择结构:根据条件判断选择要执行的语句,出口只有一个 循环结构:满足一定条件,重复执行一段代码 二.选择结构 1.三元运算符:? : ...

  5. aspcms逻辑错误导致后台地址泄露

    访问即可跳转后台地址: URL:http://www.xxx.org.cn/plug/oem/AspCms_OEMFun.asp 注入:plug/comment/commentList.asp?id= ...

  6. 【知名的3D造型设计软件】犀牛 Rhinoceros 5.5.2 for Mac

    [简介] 今天和大家分享最新的3D设计软件 犀牛 Rhinoceros for Mac 5.5.2 版本,支持中文界面,这是一款Mac上知名的3D造型软件,犀牛可以广泛地应用于三维动画制作.工业制造. ...

  7. pandas知识点

    1.选择对象 1.选择特定列和行的数据 a['x'] 那么将会返回columns为x的列,注意这种方式一次只能返回一个列.a.x与a['x']意思一样. 取行数据,通过切片[]来选择 如:a[0:3] ...

  8. vue基础篇---watch监听

    watch可以让我们监控一个值的变化.从而做出相应的反应. 示例: <div id="app"> <input type="text" v-m ...

  9. 原生JavaScript运动功能系列(三):多物体多值运动

    多物体同时出发运动函数实现 多属性同步运动变化实现 一.多物同时触发运动函数实现 前面两个动画示例基本理解了动画的核心:位置变化和速度变化,操作的核心就是定时器分段叠加属性值.但是动画还是基于单个元素 ...

  10. Redis基本概念、基本使用与单机集群部署

    1. Redis基础 1.1 Redis概述 Redis是一个开源.先进的key-value存储,并用于构建高性能.可扩展的应用程序的完美解决方案. Redis从它的许多竞争继承了三个主要特点:    ...