《Entity Framework 6 Recipes》中文翻译系列 (24) ------ 第五章 加载实体和导航属性之查询内存对象
翻译的初衷以及为什么选择《Entity Framework 6 Recipes》来学习,请看本系列开篇
5-4 查询内存对象
问题
你想使用模型中的实体对象,如果他们已经加载到上下文中,便不用与数据库发生交互。另外,你想使用Code-First来管理数据访问。
解决方案
假设你有如图5-12所示的模型。
图5-12 一个包含Club实体对象的简单模型
在Visual Studio中添加一个名为Recipe4的控制台应用,并确保引用了实体框架6的库,NuGet可以很好的完成这个任务。在Reference目录上右键,并选择 Manage NeGet Packages(管理NeGet包),在Online页,定位并安装实体框架6的包。这样操作后,NeGet将下载,安装和配置实体框架6的库到你的项目中。
创建一个名为Club类,复制代码清单5-8中的属性到这个类中,创建club实体。
代码清单5-8. Club实体类
public class Club
{
public int ClubId { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
接下来,创建一个名为Recipe4Context的类,并将代码清单5-9中的代码添加到其中,并确保其派生到DbContext类。
代码清单5-9. 上下文对象Recipe4Contex
1 public class Recipe4Context : DbContext
2 {
3 public Recipe4Context()
4 : base("Recipe4ConnectionString")
5 {
6 // 禁用实体框架的模型兼容性
7 Database.SetInitializer<Recipe3Context>(null);
8 }
9
10 protected override void OnModelCreating(DbModelBuilder modelBuilder)
11 {
12 modelBuilder.Entity<Club>().ToTable("Chapter5.Club");
13 }
14
15 public DbSet<Club> Clubs { get; set; }
16 }
接下来添加App.Config文件到项目中,并使用代码清单5-10中的代码添加到文件的ConnectionStrings小节下。
代码清单5-10. 连接字符串
<connectionStrings>
<add name="Recipe4ConnectionString"
connectionString="Data Source=.;
Initial Catalog=EFRecipes;
Integrated Security=True;
MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
在这个模型中,我们有一个实体类型Club,你可以通过查询获取各种各样的俱乐部(Clubs). 我们可以通过查询DbSet的属性Local来减少与数据库的交互。它是对Club实体的包装。属性Local 公布了一个内存实体对象的动态集合(Observable Collection),与上下文对象保持同步。代码清单5-11演示了Local动态集合的用法。
代码清单5-11. DbSet对象中Local 属性的一般用法
int desertSunId; using (var context = new Recipe4Context())
{
var starCity = new Club {Name = "Star City Chess Club", City = "New York"};
var desertSun = new Club {Name = "Desert Sun Chess Club", City = "Phoenix"};
var palmTree = new Club {Name = "Palm Tree Chess Club", City = "San Diego"}; context.Clubs.Add(starCity);
context.Clubs.Add(desertSun);
context.Clubs.Add(palmTree); context.SaveChanges(); desertSunId = desertSun.ClubId;
} using (var context = new Recipe4Context())
{
Console.WriteLine("\nLocal Collection Behavior");
Console.WriteLine("================="); Console.WriteLine("\nNumber of Clubs Contained in Local Collection: {0}", context.Clubs.Local.Count);
Console.WriteLine("================="); Console.WriteLine("\nClubs Retrieved from Context Object");
Console.WriteLine("=================");
foreach (var club in context.Clubs.Take())
{
Console.WriteLine("{0} is located in {1}", club.Name, club.City);
} Console.WriteLine("\nClubs Contained in Context Local Collection");
Console.WriteLine("=================");
foreach (var club in context.Clubs.Local)
{
Console.WriteLine("{0} is located in {1}", club.Name, club.City);
} context.Clubs.Find(desertSunId); Console.WriteLine("\nClubs Retrieved from Context Object - Revisted");
Console.WriteLine("=================");
foreach (var club in context.Clubs)
{
Console.WriteLine("{0} is located in {1}", club.Name, club.City);
} Console.WriteLine("\nClubs Contained in Context Local Collection - Revisted");
Console.WriteLine("=================");
foreach (var club in context.Clubs.Local)
{
Console.WriteLine("{0} is located in {1}", club.Name, club.City);
} //获取local集合的引用
var localClubs = context.Clubs.Local; // 添加一个新的 Club
var lonesomePintId = -;
localClubs.Add(new Club
{
City = "Portland",
Name = "Lonesome Pine",
ClubId = lonesomePintId
}); // 删除 Desert Sun club
localClubs.Remove(context.Clubs.Find(desertSunId)); Console.WriteLine("\nClubs Contained in Context Object - After Adding and Deleting");
Console.WriteLine("=================");
foreach (var club in context.Clubs)
{
Console.WriteLine("{0} is located in {1} with a Entity State of {2}",
club.Name, club.City, context.Entry(club).State);
} Console.WriteLine("\nClubs Contained in Context Local Collection - After Adding and Deleting");
Console.WriteLine("=================");
foreach (var club in localClubs)
{
Console.WriteLine("{0} is located in {1} with a Entity State of {2}",
club.Name, club.City, context.Entry(club).State);
} Console.WriteLine("\nPress <enter> to continue...");
Console.ReadLine();
代码清单5-11的输出如下:
Local Collection Behavior
=================
Number of Clubs Contained in Local Collection:
=================
Clubs Retrieved from Context Object
=================
Star City Chess Club is located in New York
Desert Sun Chess Club is located in Phoenix
Clubs Contained in Context Local Collection
=================
Star City Chess Club is located in New York
Desert Sun Chess Club is located in Phoenix
Clubs Retrieved from Context Object - Revisted
=================
Star City Chess Club is located in New York
Desert Sun Chess Club is located in Phoenix
Palm Tree Chess Club is located in San Diego
Clubs Contained in Context Local Collection - Revisted
=================
Star City Chess Club is located in New York
Desert Sun Chess Club is located in Phoenix
Palm Tree Chess Club is located in San Diego
Clubs Contained in Context Object – After Adding and Deleting
=================
Star City Chess Club is located in New York with a Entity State of Unchanged
Desert Sun Chess Club is located in Phoenix with a Entity State of Deleted
Palm Tree Chess Club is located in San Diego with a Entity State of Unchanged
Clubs Contained in Context Local Collection – After Adding and Deleting
=================
Star City Chess Club is located in New York with a Entity State of Unchanged
Palm Tree Chess Club is located in San Diego with a Entity State of Unchanged
Lonesome Pine is located in Portland with a Entity State of Added
原理
这个示例使用Club实体对象。开始,我们从Local属性公布的动态集合中获取Club实体对象的数量。注意,图5-13没有SQL查询产生,因为一个对Local属性的查询,是不会产生针对数据库的SQL查询的。
图5-13 访问Local动态集合,不会产生一个SQL查询
现在,结果为0,因为我们还没有通过上下文对象执行一个关于Clubs的查询。记住,Local动态集合会自动地与上下文对象保持同步。
接下来,我们通过上下文对象在数据库中查询前面两个Club实体。并循环输出他们的名称和地点。如图5-14所示。
图5-14 查询上下文对象,总是产生一个SQL查询
随后,我们立即循环相应的Local集合,得到了相同的结果。记住,结果集完全一样,因为Local集合自动与DbContext保持同步。如果新的实体被获取到上下文,通过这些实体,Loacal集合会被自动更新。注意,图5-15中,当访问Local集合时,没有SQL查询生成。
图5-15 访问 local集合,没有生成SQL语句
为了进一步演示Local属性的默认行为,我们通过上下文查询获取第三个Club实体,我们又一次循环上下文对象和Local集合,同样得到了相同的结果。图5-16中,通过查询上下文对象的查询产生了一个SQL语句,图5-17中,能通查询Local集合的查询,没有产生任何SQL语句。
图5-16 查询上下文对象,总是产生一个SQL查询
图5-17 访问 local集合,没有生成SQL语句
接下来,我们添加一个名为 Lonesone Pine Club实体到Local集合中,同时,我们从Local集合中删除Desert Sun Club. 然后我们枚举上下文对象中的Clubs,正如期望的那样,一个SQL查询产生了,如图5-18所示。
图5-18 查询上下文对象,总是产生一个SQL查询
有趣的是,我们看到,在上下文中Desert Sun Club已经被标记为删除,但我们没有看到最新添加的Lonesome Pine Club对象。记住,Lonesome Pine Club已经被添加到上下文中,但我们还没有调用SaveChanges()方法更新到底层据库中。
然而,当我们枚举Local集合时,没有产生针对底层数据库的查询,如图5-19所示。相反,我们看到了最新添加的Lonesome Pine Club对象,但我们不再看到标记为删除的Desert Sun Club对象。 Loacl集合的默认行为是,隐藏任何标记为删除的对象,因为这些对象不于有效。
图5-19 访问 local集合,没有生成SQL语句
本质:访问Local集合不会产生针对底层数据库的SQL查询,访问上下中的属性集合总是会产生一个被发送到数据库中的SQL是查询。
总之,名为Local的属性公布的实体集,是一个动态的集合(Observale Collection)(译注:也有人译为,可观察的集合,但综合该对象的作用和功能来看,个人认为译为动态集合更恰当一些),它是上下文内容的一个镜像。正如本小节演示的那样,查询Local集合非常有效,因为它不会产生针对底层数据库的SQL查询。
实体框架交流QQ群: 458326058,欢迎有兴趣的朋友加入一起交流
谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/
《Entity Framework 6 Recipes》中文翻译系列 (24) ------ 第五章 加载实体和导航属性之查询内存对象的更多相关文章
- 《Entity Framework 6 Recipes》中文翻译系列 (22) -----第五章 加载实体和导航属性之延迟加载
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第五章 加载实体和导航属性 实体框架提供了非常棒的建模环境,它允许开发人员可视化地使 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (28) ------ 第五章 加载实体和导航属性之测试实体是否加载与显式加载关联实体
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-11 测试实体引用或实体集合是否加载 问题 你想测试关联实体或实体集合是否已经 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (23) -----第五章 加载实体和导航属性之预先加载与Find()方法
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-2 预先加载关联实体 问题 你想在一次数据交互中加载一个实体和与它相关联实体. ...
- 《Entity Framework 6 Recipes》中文翻译系列 (25) ------ 第五章 加载实体和导航属性之加载完整的对象图和派生类型上的导航属性
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-5 加载完整的对象图 问题 你有一个包含许多关联实体的模型,你想在一次查询中, ...
- 《Entity Framework 6 Recipes》中文翻译系列 (26) ------ 第五章 加载实体和导航属性之延缓加载关联实体和在别的LINQ查询操作中使用Include()方法
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-7 在别的LINQ查询操作中使用Include()方法 问题 你有一个LINQ ...
- 《Entity Framework 6 Recipes》中文翻译系列 (27) ------ 第五章 加载实体和导航属性之关联实体过滤、排序、执行聚合操作
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-9 关联实体过滤和排序 问题 你有一实体的实例,你想加载应用了过滤和排序的相关 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (29) ------ 第五章 加载实体和导航属性之过滤预先加载的实体集合和修改外键关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-13 过滤预先加载的实体集合 问题 你想过滤预先加载的实体集合,另外,你想使用 ...
- 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述
微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...
- 《Entity Framework 6 Recipes》翻译系列 (4) -----第二章 实体数据建模基础之从已存在的数据库创建模型
不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多.不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题. 2-2 从已存在的数据库创 ...
随机推荐
- react native 刷新机制----通知
在项目中,不知道大家有没有遇到这样的一个问题,比如说有两个页面A,B.A页面中有某个按钮点击后可以跳转到B页面,现在有一个需求就是,我在B页面中做了某些操作,然后点击回退按钮,回到A页面,A页面中的数 ...
- POJ 1743 Musical Theme ——后缀数组
[题目分析] 其实找最长的不重叠字串是很容易的,后缀数组+二分可以在nlogn的时间内解决. 但是转调是个棘手的事情. 其实只需要o(* ̄▽ ̄*)ブ差分就可以了. 背板题. [代码] #include ...
- iOS 为键盘添加隐藏按钮
// 为键盘添加隐藏按钮 UIToolbar * backView = [[UIToolbar alloc]initWithFrame:CGRectMake(, , , )]; [backView s ...
- [R]R语言中的%>%和%.%
最近在网上看R的代码,常常看到 x %>% y 的写法. 样子看着像是pipe的用法,搜了一下, 没找到语法的相关说明. 今天突然开窍,想着 %>% 可能不是语言本身支持的语法,可能是某个 ...
- 【转】SHELL中的IFS详解
转自:http://smilejay.com/2011/12/bash_ifs/ 在bash中IFS是内部的域分隔符,manual中对其的叙述如下: IFS The Internal Field Se ...
- 关于在header里增加参数的方式
在使用一个API的时候,文档里写的返回值类型是json,可是试了下返回的明明是xml,还小小的鄙视了一把. 可是解析xml,好麻烦的.最好是json可以直接decode . 意外看到文档下面有一句 J ...
- js兼容总结之获取非行间样式
非行间样式案例 #div1 { width: 200px; height: 200px; background: red; } IE获取非行间样式 var oDiv = document.getEle ...
- 最简单的android自定义进度条样式
一.自定义圆形进度条样式 1.在安卓项目drawable目录下新建一个xml文件如下:<?xml version="1.0" encoding="utf-8&quo ...
- 关于ajax为什么会返回php整个源码
ajax 程序:返回的是php文件输出的代码. 1. 注意:如果你的php文件包含了html代码或者说是输出了HTML代码,它都会返回给 AJAX. 2. 注意:是整个php文件.这意味着如果你的aj ...
- 数字对象NSNumber
//将int类型转化成对象 ; NSNumber *numberString = [NSNumber numberWithInt:number]; //对象是可以放入数组的 NSArray *arra ...