Entity Framework提供了三种加载相关实体的方法:Lazy Loading,Eager Loading和Explicit Loading。首先我们先来看一下MSDN对三种加载实体方法的定义。

Lazy Loading:对于这种类型的加载,在您访问导航属性时,会从数据源自动加载相关实体。 使用此加载类型时,请注意,如果实体尚未在 ObjectContext 中,则您访问的每个导航属性都会导致针对数据源执行一个单独的查询。

Eager Loading:当您了解应用程序需要的相关实体的图形的确切形状时,可以使用 ObjectQuery 的 Include 方法来定义查询路径,此查询路径控制将哪些相关实体作为初始查询的一部分返回。 当定义查询路径时,仅需对数据库请求一次,即可在单个结果集中返回查询路径所定义的所有实体,并且属于在路径中定义的类型的所有相关实体将随查询返回的每个对象一起加载。

Explicit Loading:将实体显式加载到 ObjectContext 需要多次往返数据库,并且可能需要多个活动结果集,但是返回的数据量仅限于所加载的实体。 可以对 EntityCollection或 EntityReference 使用 Load 方法或对 ObjectContext 使用 LoadProperty 方法,以便从数据源显式检索相关实体。 对于 Load 方法的每个调用都会打开与数据库的连接,以检索相关信息。 这可确保在没有对相关实体的显式请求时,始终不会执行查询。

下面我们就以上三种加载方式来一一进行测试

在测试之前,我们先建立一个测试用的数据库,并在其中插入一些数据:

图1

Lazy Loading

在Entity Framework4.0及其以后版本,LazyLoading是默认打开的,从数据库生成Model后,我们可以在EDMX文件空白处单击,并在属性窗口看到这一设置:

图2

也可以以XML形式打开EDMX文件,在CSDL部分看到这一设置:

 1  <!-- CSDL content -->
2 <edmx:ConceptualModels>
3 <Schema Namespace="TestModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
4 <EntityContainer Name="TestEntities" annotation:LazyLoadingEnabled="true">
5 <EntitySet Name="Players" EntityType="TestModel.Player" />
6 <EntitySet Name="PlayerDetails" EntityType="TestModel.PlayerDetail" />
7 <EntitySet Name="Teams" EntityType="TestModel.Team" />
8 <AssociationSet Name="FK_Player_Team1" Association="TestModel.FK_Player_Team1">
9 <End Role="Team" EntitySet="Teams" />
10 <End Role="Player" EntitySet="Players" />
11 </AssociationSet>
12 <AssociationSet Name="FK_PlayerDetails_Player" Association="TestModel.FK_PlayerDetails_Player">
13 <End Role="Player" EntitySet="Players" />
14 <End Role="PlayerDetails" EntitySet="PlayerDetails" />
15 </AssociationSet>
16 </EntityContainer>

注意:Lazy Loading的设置是针对所有Model的,并非某一个Model。

下面,我们写一段简单的代码来测试一下Lazy Loading:

using (var context = new TestEntities())
{
IQueryable<Team> teams = from t in context.Teams select t;
foreach (Team t in teams)
{
Console.WriteLine(t.Players.Count());
}
Console.Read();
}

运行后的结果如下图:

图3

我们可以看到,在query语句中,我们只是要求返回所有的team信息,并没有像数据库请求加载player的信息,但在Foreach语句中,我们要求打印出每支team的player数量,却成功了,这就是Lazy Loading实现的效果。实际上,当执行Count语句时,程序会再去取请求数据库,返回player信息,这也就是说,如果我们有100支球队,程序会访问100次数据库来执行此操作。

下面我们关闭Lazy Loading来看看效果。关闭Lazy Loading有多种方法,我们可以在图2的属性窗口直接将Lazy Loading Enabled设置为False,也可以在XML代码中将Lazy Loading Enabled赋值False,以下我们用程序代码来关闭Lazy Loading并执行上面代码来看一下效果:

using (var context = new TestEntities())
{
//Disable Lazy Loading
context.ContextOptions.LazyLoadingEnabled = false; IQueryable<Team> teams = from t in context.Teams select t;
foreach (Team t in teams)
{
Console.WriteLine(t.Players.Count());
}
Console.Read();
}

执行结果如下:

图4

从执行结果我们可以看到,当执行Foreach语句时,程序并没有去查询数据库,而我们的query语句又没有向数据库请求关于player的信息,故无法打印出player的数量。

最后我们来总结一下Lazy Loading的优势和劣势:当打开Lazy Loading时,我们可以不用去在意某实体是否已经加载,不会出现在调用某一实体时,出现null的尴尬,省去程序员不少心力,但同时劣势也非常明显,如果我们有大量实体,且频繁去调用相关实体,程序就会频繁地访问数据库,这很显然地会影响程序的性能。

下一次我们会来分析关闭Lazy Loading的情况下,如何显示加载相关实体,即Explicit Loading。

上一回我们在《Entity Framework加载相关实体——Lazy Loading》分析了Lazy Loading,这一回我们来分析一下在关闭Lazy Loading的情况下,如果显式加载实体。

数据库我们依旧使用Lazy Loading中使用的数据库。之前我们分析过来,当Lazy Loading关闭时,执行以下代码是无法得到结果的,因为Player的信息并没有被加载。

1  using (TestEntities context = new TestEntities())
2 {
3 IQueryable<Team> teams = from t in context.Teams select t;
4 foreach (Team t in teams)
5 {
6 Console.WriteLine(t.Players.Count());
7 }
8 Console.Read();
9 }

如果我们想要得到t.Players.Count()的结果,我们可以显式地加载Player信息:

 1 using (TestEntities context = new TestEntities())
2 {
3 IQueryable<Team> teams = from t in context.Teams select t;
4 foreach (Team t in teams)
5 {
6 //explicitly loading players
7 t.Players.Load();
8 Console.WriteLine(t.Players.Count());
9 }
10 Console.Read();
11 }

当t.Players.Load()执行时,Object Service会向数据库发出请求返回该team的所有player信息。

我们也可以从many端加载与它相对应的one端,在这个例子中也就是从Player加载与该player相对应的team信息。这里需要用到TeamReference:

 1  using (TestEntities context = new TestEntities())
2 {
3 IQueryable<Player> players = from p in context.Players select p;
4 foreach (Player p in players)
5 {
6 if (p.Age > 30)
7 {
8 p.TeamReference.Load();
9 Console.WriteLine(p.PlayerName + " -> " + p.Team.TeamName);
10 }
11 }
12 Console.Read();
13 }

执行结果如下:

当我们打出p.后会发现,智能提示中出现了Team和TeamReference,这里我们选择TeamReference,因为EF将p.Team认为就是一个Team实体。

无论使用Lazy Loading还是将Load方法放入foreach循环语句,都会导致程序频繁访问数据库,导致程序性能下降。我们可以选择性地加载需要的实体,例如上面代码,我们只加载年龄超过30岁的球员所在球队的信息。

至此,Lazy Loading和Explicit Loading都已经分析完了,下一次我们来分析加载相关实体的最后一种形式Eager Loading.

在前面两回我们分别分析了Lazy LoadingExplicit Loading,这一回我们来分析一下Eager Loading。

在某些情况下,我们可能事先知道要需要加载某些实体的相关实体,这时我们就可以用Include方法来在加载实体的查询语句中把相关实体也一并查询出来。下面我们还用前两回使用的数据库来写一个例子来分析一下Eager Loading:

 1 using (var context = new TestEntities())
2 {
3 var players = from p in context.Players.Include("Team").Include("PlayerDetails") where (p.PlayerDetails.Any(d => d.Height > 200)) select p;
4 foreach (var v in players)
5 {
6 string output = string.Format("Team: {0} Player: {1}", v.Team.TeamName, v.PlayerName);
7 Console.WriteLine(output);
8 }
9 Console.Read();
10 }

以上代码,我们查询出了身高在2米以上的球员的名字和所在球队,在查询Player信息的同时,也查询了Team表和PlayerDetails表的信息,将三个表的信息全部加载了进来。这里我们需要注意,我们可以控制将哪些相关实体加载入内,但不能够对Include进来的实体进行筛选,如以下代码:

1 var teams = from t in context.Teams.Include("Players") where (t.TeamID == 1) select t;

我们可以选择加载哪些球队,却不能选择加载球队的哪些球员,该球队的所有球员都将被加载进来。

至此,Entity Framework加载相关实体的三种形式全部分析完毕!

Entity Framework加载相关实体——延迟加载Lazy Loading、贪婪加载Eager Loading、显示加载Explicit Loading的更多相关文章

  1. 《Entity Framework 6 Recipes》中文翻译系列 (43) ------ 第八章 POCO之使用POCO加载实体

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-2  使用POCO加载关联实体 问题 你想使用POCO预先加载关联实体. 解决方 ...

  2. Entity Framework 第三篇 实体特性声明

    Entity Framework中对实体的特性声明有着严格的要求 1.实体必须要有主键特性,但是如果实体没有主键特性那怎么办? public int ExecuteSqlCommand(string ...

  3. Entity Framework应用:根据实体的EntityState状态实现增删改查

    在上一篇文章中,我们讲解了使用EF实现简单的增删改成,在这篇文章中我们使用实体的EntityState状态来优化数据的增删改查. 一.修改数据 上篇文章中的修改数据的方法是EF官方推荐的方式,即先查询 ...

  4. Entity Framework Core一键生成实体命令

    打开Vs中工具——Nug包管理器——程序包管理控制台 设置启动项目为存储实体模型的类库或控制台 Scaffold-DbContext  "数据库连接字符串" Microsoft.E ...

  5. Entity Framework关联实体的三种加载方法

    推荐文章 EF性能之关联加载 总结很好 一:介绍三种加载方式 Entity Framework作为一个优秀的ORM框架,它使得操作数据库就像操作内存中的数据一样,但是这种抽象是有性能代价的,故鱼和熊掌 ...

  6. Entity Framework Code First实体关联数据加载

    在项目过程中,两个实体数据之间在往往并非完全独立的,而是存在一定的关联关系,如一对一.一对多及多对多等关联.存在关联关系的实体,经常根据一个实体的实例来查询获取与之关联的另外实体的实例. Entity ...

  7. 《Entity Framework 6 Recipes》中文翻译系列 (23) -----第五章 加载实体和导航属性之预先加载与Find()方法

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-2  预先加载关联实体 问题 你想在一次数据交互中加载一个实体和与它相关联实体. ...

  8. Entity Framework入门教程(8)---预先加载、延迟加载、显示加载

    1.预先加载 预先加载:在对一种类型的实体进行查询时,将相关的实体作为查询的一部分一起加载.预先加载可以使用Include()方法实现. 1.加载一个相关实体类型 栗子:使用Include()方法从数 ...

  9. Entity Framework学习笔记(五)----Linq查询(2)---贪婪加载

    请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,我们使用了Linq对Entity Framework进行了一个查询,但是通过学习我们却发现了懒加载给我来的性能上的 ...

随机推荐

  1. NYOJ 745 蚂蚁问题(两)

    蚂蚁的难题(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 下雨了,下雨了.蚂蚁搬家了. 已知有n种食材须要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种 ...

  2. 白学jquery Mobile《构建跨平台APP:jQuery Mobile移动应用实战》连续7-电话问卷调查

    [例7-3  文本编辑框创建一个简单的调查问卷] 01     <!DOCTYPEhtml> 02     <html> 03     <head> 04     ...

  3. cocos2dX 它CCScene创建原则和切换模式

    今天, 让我们来看看现场CCScene创建原则和切换模式, 首先, 个什么样子: 我们先来看看效果: 啥也没有: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZX ...

  4. C# 经典排序算法大全

    C# 经典排序算法大全 选择排序 using System; using System.Collections.Generic; using System.Linq; using System.Tex ...

  5. PHP訪问MySql数据库 0基础篇

    在站点后台,常常要与数据库打交道.本文介绍怎样使用XAMPP来管理MySql数据库及怎样用PHP来訪问MySql数据库. 一.使用XAMPP来管理MySql数据库 首先使用XAMPP打开MySql的管 ...

  6. matlab 图片批量读取

    1. 指定的路径 单目录data所有图片 file_path = '.\data\';% 图片目录路径 img_path_list = dir(strcat(file_path,'*.jpg'));% ...

  7. Java读书笔记三(字符串)

    1.介绍 本篇博客将对JAVA中的字符串类的基本知识进行介绍.主要字符串类的一些经常用法等内容. 2.字符串对象的创建 1.有两种形式.可是在开发中常常习惯于String 变量名的形式来进行操作. & ...

  8. 走向DBA[MSSQL篇] 详解游标

    原文:走向DBA[MSSQL篇] 详解游标 前篇回顾:上一篇虫子介绍了一些不常用的数据过滤方式,本篇详细介绍下游标. 概念 简单点说游标的作用就是存储一个结果集,并根据语法将这个结果集的数据逐条处理. ...

  9. linux虚拟机网络配制方法及遇到问题的解决方法

    linux虚拟机网络问题 刚安装一个vmware虚拟机.并在上面安装了一个redhat linux操作系统. 安装完后配制了下网络. 首先观察windows上的网络配制. ip:192.168.1.1 ...

  10. 站长VS微商 你选择哪个?

    近期,站长圈里盛行起了一阵面膜风.我刷空间和微信朋友圈的时候,常常看到一些朋友在卖面膜,不光女童鞋在卖,男屌丝站长也在卖. 不光普通人在卖.行业圈的自媒体明星大佬也在卖. 我们暂且称卖面膜的童鞋为微商 ...