如果你还没有接触过或者根本不了解什么是Entity Framework,那么请看这里http://www.entityframeworktutorial.net/EntityFramework-Architecture.aspx,其中的一系列文章以非常简单易懂的形式一步步介绍了Entity Framework的一些基本概念和操作方法。一句话,Entity Framework是微软新的数据操作框架,在项目中引入Entity Framework可以极大的方便开发人员完成程序与数据库的各种操作。在早期的.NET应用程序中,我们直接通过SqlConnection,SqlDataAdapter,DataReader等一些基本对象来实现与数据库的操作,与数据库的每一次交互都需要专门编写大量的代码。为了将程序员的精力从这些看似无聊的代码中释放出来,让更多的人去关注程序业务方面的操作,后来出现了各种与数据库交互的类库,有一些是开源的,也有一些是程序员自己编写的通用类库。这里面比较著名的有NHibernate.NET——一个基于Mapping的关系型数据库框架。NHibernate功能强大,不过由于配置起来稍微有点复杂并且缺少默认的VS代码生成工具,在快速小型项目中往往难以得心应手。Entity Framework (以下简称EF)的出现从根本上解决了这一问题,使得程序员可以彻底从与数据库交互的底层代码中释放出来,与数据库的交互变得前所未有的简单。

  使用EF在与关系型数据库的交互中不可避免地需要加载数据,如何加载数据变得至关重要。你可以设想在一个包含数十万条数据的表中,你如何通过EF来加载数据呢?一次性将所有数据载入服务器内存或者在循环中一遍又一遍地分步加载数据?使用什么样的数据加载方式需要具体问题具体分析,我们不能在这里笼统地下决定说哪种方式好哪种方式不好。但有一点是需要遵循的,那就是如何提高数据加载的效率。EF提供了几种不同的数据加载方式,我们可以根据不同的需要灵活使用它们。

  先简单说一下如何创建环境。如果你对这些步骤了如指掌,请直接跳过。

1. 在Visual Studio中创建一个示例工程。最简单的莫过于ConsoleApplication

2. 在工程中添加ADO.NET Entity Data Model。如下图所示,

  选择其中的两个表作为示例,表Teacher和表Course,关系如下,

  添加edmx之后,Visual Studio为自动帮我们生成/添加所有需要的文件和内容,然后我们就可以开始在代码中操作数据库了。来看看在EF中几种不同的数据加载方式。

惰性加载(Lazy Loading)

  默认情况下,EF会使用惰性加载方式加载数据,即ctx.Configuration.LazyLoadingEnabled = true; 在下面的代码中,外层循环会执行一次查询,并将返回的结果存放在变量q中。而内层循环会在每一次循环过程中独立进行查询,所以,如果数据库表Teacher中有100条记录而Course有1000条记录,那么整个过程将产生1001次查询。

using (var ctx = new SchoolDBEntities())
{var q = from t in ctx.Teachersselect t;foreach (var teacher in q){Console.WriteLine("Teacher : {0}", teacher.TeacherName);Console.WriteLine("Respective Courses...");foreach (var course in teacher.Courses){Console.WriteLine("Course name : {0}", course.CourseName);}Console.WriteLine();Console.ReadKey();}
}

  下面是程序执行的结果以及在SQL Server Profiler中的跟踪记录。可以清楚地看到,对表Teacher只进行了一次查询,由于该表只有8条记录,于是在内层循环中又分别产生了8次对表Course的查询。

  在某些场合下,这种情况是可以接受的。你完全可以根据需要来控制内层循环何时显示加载数据,或者根本不加载数据。但是,在分层结构的应用程序中,上述代码结构并不适用,因为内层循环需要依赖于外层的Context,也就是说它们是在同一个数据库上下文中完成的,如果尝试将内层循环的代码移到外面或者其它类中,则它将获取不到任何数据。

显式加载(Explicit Loading)

  如果你想人为控制惰性加载的行为,可以尝试使用下面的代码。首先需要手动关闭EF的惰性加载,通过代码ctx.Configuration.LazyLoadingEnabled = false;来完成。

using (var ctx = new SchoolDBEntities())
{ctx.Configuration.LazyLoadingEnabled = false;var q = from t in ctx.Teachersselect t;foreach (var teacher in q){Console.WriteLine("Teacher : {0}", teacher.TeacherName);Console.WriteLine("Respective Courses...");// Conditionally load the child dataif (true){ctx.Entry(teacher).Collection(c => c.Courses).Load();}foreach (var course in teacher.Courses){Console.WriteLine("Course name : {0}", course.CourseName);}Console.WriteLine();Console.ReadKey();}
}

  注意内层循环只有在上面高亮显示部分的代码执行之后才会获取到数据,否则返回结果为0。通过添加判断条件,我们可以对数据加载方式进行控制,从而有效地减少程序与数据库交互的次数。大多数情况下,我们从数据库获取到的数据并不都是有用的,如果每次只有很少一部分数据有用,那么我们为什么不过滤掉那些无用的数据从而尽量较少数据交互的次数呢?

预先加载(Eager Loading)

  如果你想让所有数据一次性全部加载到内存中,那么你需要使用.Include(Entity)方法。看下面的代码,

using (var ctx = new SchoolDBEntities())
{var q = from t in ctx.Teachers.Include("Courses")select t;foreach (var teacher in q){Console.WriteLine("Teacher : {0}", teacher.TeacherName);Console.WriteLine("Respective Courses...");foreach (var course in teacher.Courses){Console.WriteLine("Course name : {0}", course.CourseName);}Console.WriteLine();Console.ReadKey();}
}

  如果你查看SQl Server Profiler中的跟踪信息,你会发现只有一次数据交互过程,即程序只通过一次查询便获取到了所有需要的数据。在分层结构中,该方法是最容易的,我们可以将数据库底层获取到的结果返回给上层,它不具有任何依赖项。同时,它也可以减少程序与数据库的交互次数。不过仍然有缺点,那就是如果数据量较大,一次性将所有数据载入内存往往并不是最明智的选择。.Include(Entity)方法允许级联使用,你可以预先加载具有多层级结构的数据。

  就像前面所说,选择什么样的数据加载方式需要因时而异,每一种数据加载方式都有它存在的意义,但目的只有一个,那就是以最少的代价获取到需要的数据。

相关文章:Loading Related Objects (Entity Framework)

浅谈Entity Framework中的数据加载方式相关推荐

  1. 嵌入式AI —— 6. 为糖葫芦加糖,浅谈深度学习中的数据增广

    没有读过本系列前几期文章的朋友,需要先回顾下已发表的文章: 开篇大吉 集成AI模块到系统中 模型的部署 CMSIS-NN介绍 从穿糖葫芦到织深度神经网络 又和大家见面了,上次本程序猿介绍了CMSIS- ...

  2. Pytorch中的数据加载

    Pytorch中的数据加载 1. 模型中使用数据加载器的目的 在前面的线性回归模型中,使用的数据很少,所以直接把全部数据放到模型中去使用. 但是在深度学习中,数据量通常是都非常多,非常大的,如此大量的 ...

  3. c语言文件 加载内存吗,把文件中的数据加载到内存进行查找C语言实现.docx

    把文件中的数据加载到内存进行查找C语言实现 #define _CRT_SECURE_NO_WARNINGS#include#include#includechar **pp=NULL;void ini ...

  4. Spark _25.plus _使用idea读取Hive中的数据加载成DataFrame/DataSet(四)

    对Spark _25 _读取Hive中的数据加载成DataFrame/DataSet(四) https://georgedage.blog.csdn.net/article/details/10309 ...

  5. Spark _25 _读取Hive中的数据加载成DataFrame/DataSet(四)

    由于Hive不在本地,操作略显麻烦.不过细心一点,分析错误,也还好,如果你搭建的hadoop是HA,需要多注意: 这里指出一个错误,如果你报了同类错误,可以参考:https://georgedage. ...

  6. pytorch中的数据加载(dataset基类,以及pytorch自带数据集)

    目录 pytorch中的数据加载 模型中使用数据加载器的目的 数据集类 Dataset基类介绍 数据加载案例 数据加载器类 pytorch自带的数据集 torchvision.datasets MIN ...

  7. 【学习系列7】Pytorch中的数据加载

    目录 1. 模型中使用数据加载器的目的 2. 数据集类 3. 迭代数据集 1. 模型中使用数据加载器的目的 在前面的线性回归横型中,我们使用的数据很少,所以直接把全部数据放到锁型中去使用. 但是在深度 ...

  8. android fragment加载布局的方式,Android中Fragment的加载方式与数据通信详解

    Android中Fragment的加载方式与数据通信详解 发布时间:2020-08-22 18:55:57 来源:脚本之家 阅读:155 作者:Joah 一.加载方式 1. 静态加载 1.1 加载步骤 ...

  9. HTML 中 JavaScript 的加载方式

    HTML中 JavaScript 的加载方式 前言 相信各位前端的小伙伴都用过script元素,今天我们就来好好聊一聊它. script元素 将JavaScript插入HTML的主要方法是使用〈〉元素 ...

最新文章

  1. Androidx CoordinatorLayout 和 AppBarLayout 实现折叠效果(通俗的说是粘性头效果)
  2. word2vec_文本相似度
  3. 赠书:响应式编程到底是什么?
  4. 电脑软件:推荐八款提高工作效率的软件,值得收藏!
  5. 重命名Heroku的app
  6. android 微信webview,android实现用户体验超棒的微信WebView进度条
  7. python 条形图 负值_Python处理JSON数据并生成条形图
  8. oracle 新建命令文件命令行,Oracle11.2 命令行手工最简创建数据库的过程
  9. 第二章 jQuery选择器
  10. PKUSC2019划水记
  11. dcdc升压计算器excel_DC-DC升降压芯片(MC34063A/33063)典型电路与元件参数在线计算_三贝计算网_23bei.com...
  12. froala 的使用
  13. Cmake查找所有指定cpp文件并进行编译
  14. leetcode 904 水果成篮
  15. WEB端支付宝接入----统一收单下单并支付页面接口
  16. 2019年北京理工大学计算机专硕上岸经验分享
  17. 易基因|Science:单细胞甲基化测序鉴定哺乳动物的新神经元亚型和调节元件
  18. 关于ul ol li
  19. mysql导入excel
  20. SQL直接计算年龄问题

热门文章

  1. 实习语录@秒针系统[上]
  2. 问题解决:./config.sh: line 103
  3. 改了个字符串 项目无法启动,springboot循环依赖问题分析
  4. es管理kabina_ES和Kibana在Linux上的安装
  5. 希捷四十载:如何做好一家非常规存储公司?
  6. Linux进程地址空间和虚拟内存
  7. C# 之 Excel 导入一列中既有汉字又有数字:数字可以正常导入,汉字导入为空
  8. Android中文API(134) —— Account
  9. 8-1 数据库分库分表的几种方式
  10. mysql+查看端口和进程,linux查看端口、进程以及kill情况