热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自己来控制EntityFramework4.1Code-First,强大的EF多种加载方式

众所周知,EF对关系表的联表查询有2种方式:延迟加载、贪婪加载,为了弄清这2种方式具体是如何操作数据库的,我开启了SQLServerProfiler,只开启了存储过程和TSQL的监视,并且指定了当

众所周知,EF对关系表的联表查询有2种方式:延迟加载、贪婪加载,为了弄清这2种方式具体是如何操作数据库的,我开启了SQL Server Profiler,只开启了存储过程和TSQL的监视,并且指定了当前操作的库。

   //3联表,Order Product Category
1. var ordercOntext= db.OrderContext.Include(o => o.Product); //外键表贪婪一个,延迟一个Category 
2. var ordercOntext= db.OrderContext.Include(o => o.Product).Include(o=>o.Product.Category) //外键表全贪婪
3. var ordercOntext= db.OrderContext;  //外键表全延时

对应生成的SQL并执行的语句为:查询输出100条记录

1.半延迟半贪婪  3次数据库查询
执行时间:0.0181664 
解析时间:0.0629575
总时间:0.0811491
SELECT 
[Extent1].[ID] AS [ID],
[Extent1].[Product_ID] AS [Product_ID],
[Extent1].[Name] AS [Name],
[Extent1].[Address] AS [Address],
[Extent1].[CreateTime] AS [CreateTime],
[Extent2].[ID] AS [ID1],
[Extent2].[Name] AS [Name1],
[Extent2].[CategoryID] AS [CategoryID],
[Extent2].[Price] AS [Price]
FROM  [dbo].[Order] AS [Extent1]
INNER JOIN [dbo].[Product] AS [Extent2] ON [Extent1].[Product_ID] = [Extent2].[ID]
 
 
exec sp_executesql N'SELECT 
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[CategoryName] AS [CategoryName],
[Extent1].[IsDel] AS [IsDel]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[CategoryID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
 
 
exec sp_executesql N'SELECT 
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[CategoryName] AS [CategoryName],
[Extent1].[IsDel] AS [IsDel]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[CategoryID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=2
 
 
 
 
2. 全贪婪  1次数据库查询
执行时间:0.0173032 
解析时间:0.0533344
总时间:0.0706627
SELECT 
[Extent1].[ID] AS [ID],
[Extent1].[Product_ID] AS [Product_ID],
[Extent1].[Name] AS [Name],
[Extent1].[Address] AS [Address],
[Extent1].[CreateTime] AS [CreateTime],
[Extent2].[ID] AS [ID1],
[Extent2].[Name] AS [Name1],
[Extent2].[CategoryID] AS [CategoryID],
[Extent2].[Price] AS [Price],
[Extent4].[CategoryID] AS [CategoryID1],
[Extent4].[CategoryName] AS [CategoryName],
[Extent4].[IsDel] AS [IsDel]
FROM    [dbo].[Order] AS [Extent1]
INNER JOIN [dbo].[Product] AS [Extent2] ON [Extent1].[Product_ID] = [Extent2].[ID]
LEFT OUTER JOIN [dbo].[Product] AS [Extent3] ON [Extent1].[Product_ID] = [Extent3].[ID]
LEFT OUTER JOIN [dbo].[Category] AS [Extent4] ON [Extent3].[CategoryID] = [Extent4].[CategoryID]
 
 
3.全延迟加载, 延迟2个表 ,5次数据库查询
执行时间:0.0128477 
解析时间:0.0796226
总时间:0.0925025
SELECT 
[Extent1].[ID] AS [ID],
[Extent1].[Product_ID] AS [Product_ID],
[Extent1].[Name] AS [Name],
[Extent1].[Address] AS [Address],
[Extent1].[CreateTime] AS [CreateTime]
FROM [dbo].[Order] AS [Extent1]
 
 
exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[Price] AS [Price]
FROM [dbo].[Product] AS [Extent1]
WHERE [Extent1].[ID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
 
 
exec sp_executesql N'SELECT 
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[CategoryName] AS [CategoryName],
[Extent1].[IsDel] AS [IsDel]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[CategoryID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
 
 
exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[Price] AS [Price]
FROM [dbo].[Product] AS [Extent1]
WHERE [Extent1].[ID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=2
 
 
exec sp_executesql N'SELECT 
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[CategoryName] AS [CategoryName],
[Extent1].[IsDel] AS [IsDel]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[CategoryID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=2
 

三中加载方式和对应的实际操作SQL命令我贴了出来,每种方式的数据库查询次数都不同,并且延迟加载是以存储过程方式执行的语句; 细心的人可能发现我输出了执行时间,这个我是在MVC过滤器中做的定时器,虽然我已经刷新N次,取了中间值,但这个执行时间还是比较离奇,权当我机器环境不稳定了,但有点可理解的是,比如底3种,按说他应该最慢的,但并没有如此,因为第一条sql语句没有使用联表节约了时间,而其后面的4条延时加载又以存储过程方式执行提高了性能。

需要注意的是,经调试和监视SQL SERVER,发现EF对延迟加载统一使用存储过程方式执行,而贪婪式则为JOIN联表操作,此文并不作几种方式的性能评测结论,因为联表中的外键表记录只有2条,所以聪明的EF是读取所需的外键值针对性的去读库,而不是100条记录联2个表就要额外读200次外键表。自然,当数据库联表外键值较多时,或者每条主表记录的外键值都不同时,的确要读和记录相同数的数据库次数。

因地而异,并不能指定怎样去用何种方式加载,但输出关系表内容,并调用关系表字段值时,仍然建议使用贪婪式加载。


推荐阅读
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
author-avatar
梁lxc_131
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有