Entity Framework 6 Recipes 2nd Edition(13-5)译 -> 使POCO的修改追踪更高
问题
你正在使用POCO,你想提高修改跟踪的性能,同时使内存消耗更少.另外,你想通过EF的CodeFirst方式来实现.
解决方案
假设你有一个关于Account(帐户)和相关的Payments(支付)的模型,如Figure 13-7

Figure 13-7. A model with an Account entity and a related Payment
首先,本例用EF的CodeFirst方式实现,在Listing 13-16,我们创建实体类:Account和Payment.为达到最优化的修改跟踪性能,我们需要允许EF能用修改跟踪代理类自动地封装我们的实体类,代理能立即通知底层的代理跟踪机构能随时跟踪属性的修改,使用代理,EF一直都能知道你的实体的state(状态).当创建代理时,通知事件会被添加到每个属性的setter方法上,这个过程由Object State Manager(对象状态管理器)完成.当达到以下两个条件时EF会立即创建一个代理类:(1)所有的实体的属性都必须是virtual,(2)任何集合类的导航属性类型必须是Icollection<T>.EF会override满足这两个条件的实体类,并添加必要的修改跟踪装置.
我们的Account和Payment实体类符合这两件条件,如Listing 13-16 所示:
Listing 13-16. Our Entity Classes with Properties Marked as virtual and the Navigation Properties Are of Type
ICollection<T>
public class Account
{
public virtual int AccountId { get; set; }
public virtual string Name { get; set; }
public virtual decimal Balance { get; set; }
public virtual ICollection<Payment> Payments { get; set; }
}
public class Payment
{
public virtual int PaymentId { get; set; }
public virtual string PaidTo { get; set; }
public virtual decimal Paid { get; set; }
public virtual int AccountId { get; set; }
}
接下来,在Listing 13-17 我们创建用CodeFirst方式访问EF功能的途径,DbContext对象
Listing 13-17. DbContext Object
public class Recipe5Context : DbContext
{
public Recipe5Context()
: base("Recipe5ConnectionString")
{
// Disable Entity Framework Model Compatibility
Database.SetInitializer<Recipe6Context>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>().ToTable("Chapter13.Account");
modelBuilder.Entity<Payment>().ToTable("Chapter13.Payment");
}
public DbSet<Account> Accounts { get; set; }
public DbSet<Payment> Payments { get; set; }
}
接下来在项目中添加App.config类,并把Listing 13-18 的代码添加到ConnectionStrings节下
Listing 13-18. Connection String
<connectionStrings>
<add name="Recipe5ConnectionString"
connectionString="Data Source=.;
Initial Catalog=EFRecipes;
Integrated Security=True;
MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
接下来Listing 13-19 演示了插入,获取,和更新我们的模型.
Listing 13-19. Inserting, Retrieving, and Updating Our Model
using (var context = new Recipe5Context())
{
var watch = new Stopwatch();
watch.Start();
for (var i = 0; i < 5000; i++)
{
var account = new Account
{
Name = "Test" + i,
Balance = 10M,
Payments = new Collection<Payment> { new Payment { PaidTo = "Test" + (i + 1), Paid = 5M } },
};
context.Accounts.Add(account);
Console.WriteLine("Adding Account {0}", i);
}
context.SaveChanges();
watch.Stop();
Console.WriteLine("Time to insert: {0} seconds", watch.Elapsed.TotalSeconds.ToString());
}
using (var context = new Recipe5Context())
{
var watch = new Stopwatch();
watch.Start();
var accounts = context.Accounts.Include("Payments").ToList();
watch.Stop();
Console.WriteLine("Time to read: {0} seconds", watch.Elapsed.TotalSeconds.ToString());
watch.Restart();
foreach (var account in accounts)
{
account.Balance += 10M;
account.Payments.First().Paid += 1M;
}
context.SaveChanges();
watch.Stop();
Console.WriteLine("Time to update: {0} seconds", watch.Elapsed.TotalSeconds.ToString());
}
它是如何工作的
EF的最后一个版本,包含6.0,我们用POCO类来代表实体类,POCO是Plain Old CRL Object缩写,通常只包含与数据库表列对应的态和属性.POCO类没有依赖.NET CLR基类,尤其没有依赖EF的东西.
对POCO实体类的修改跟踪,要么使用快照,要么使用代理类,使用快照的方式,EF先拍张照,打个比方说,一个实体的数据值就是从一个查询后被装载入上下文时的值或一个Attach()操作.在一个SaveChanges()操作前,用原始的快照与当前数据值比对来检测是否发生过修改.用这种方式,EF维护每个对象的两个拷贝并比较它们,然后生成对应的SQL更新,插入,和删除语句.你可能会认为这种方式会比较慢,但EF在比较不同时是非常快的.
■■注意 上下文的Add()操作不会对添加的实体进行拍照,因为实体是新的,没有必要对单个的值进行修改跟踪.EF会把该实体标志为Added,在SaveChanges()操作时,会产生对应的插入SQL语句.
第二个方式,如Listing 13-19描述的,用一个实现了IentityWithChangeTracking接口的代理对象来包装底层的实体POCO对象.该代理负责通知Object State Manager(对象状态管理器)实体对象的属性和相关联对象属性的修改.EF会自动为你的POCO对象创建代理,当你把在你的POCO类里把每个属性标为virtual,把每个导航属性返回Icollection<T>类型.代理避免了可能复杂的快照方式下的对象与对象之间的比较,虽然代理也需要为跟踪每个变化的发生付出些负载.
尽管修改跟踪代理立即通知修改跟踪组件对象的修改并避免对象的比较,在实践中,性能上所带来的好处也只在模型非常复杂并只有少量的修改时,才能体现出来.Figure 13-7所示的模型非常简单,如果你改变Listing 13-19的代码,用快照的方式,你可能会注意到用代理类只快一两秒.
注意 代理类在n层结构,并且需要序列化数据并传送给另一个层(比如传一个WCF或WEB API客户端,更多查看Recipe 9-7)时,会变得比较麻烦.
Entity Framework 6 Recipes 2nd Edition(13-5)译 -> 使POCO的修改追踪更高的更多相关文章
- Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新
因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...
- Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体
第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...
- Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...
- Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪
9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...
- Entity Framework 6 Recipes 2nd Edition(13-2)译 -> 用实体键获取一个单独的实体
问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Paint ...
- Entity Framework 6 Recipes 2nd Edition(13-3)译 -> 为一个只读的访问获取实体
问题 你想有效地获取只是用来显示不会更新的操作的实体.另外,你想用CodeFirst的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种 ...
- Entity Framework 6 Recipes 2nd Edition(13-4)译 -> 有效地创建一个搜索查询
问题 你想用LINQ写一个搜索查询,能被转换成更有效率的SQL.另外,你想用EF的CodeFirst方式实现. 解决方案 假设你有如下Figure 13-6所示的模型 Figure 13-6. A s ...
- Entity Framework 6 Recipes 2nd Edition(13-9)译 -> 避免Include
问题 你想不用Include()方法,立即加载一下相关的集合,并想通过EF的CodeFirst方式实现. 解决方案 假设你有一个如Figure 13-14所示的模型: Figure 13-14. A ...
- Entity Framework 6 Recipes 2nd Edition(目录索引)
Chapter01. Getting Started with Entity Framework / 实体框架入门 1-1. A Brief Tour of the Entity Framework ...
随机推荐
- .Net中的AOP系列之构建一个汽车租赁应用
返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...
- C语言 · 4-3水仙花数
问题描述 打印所有100至999之间的水仙花数.所谓水仙花数是指满足其各位数字立方和为该数字本身的整数,例如 153=1^3+5^3+3^3. 样例输入 一个满足题目要求的输入范例.例:无 样例输出 ...
- ExtJS 4.2 业务开发(一)主页搭建
本篇开始搭建一个ExtJS 4.2单页面应用, 这里先介绍主页的搭建,内容包括:主页结构说明.扩展功能等方面. 目录 1. 主页结构说明 2. 扩展功能 3. 在线演示 1. 主页结构说明 1.1 主 ...
- Oracle 数据库知识汇总篇
Oracle 数据库知识汇总篇(更新中..) 1.安装部署篇 2.管理维护篇 3.数据迁移篇 4.故障处理篇 5.性能调优篇 6.SQL PL/SQL篇 7.考试认证篇 8.原理体系篇 9.架构设计篇 ...
- git克隆项目到本地&&全局安装依赖项目&&安装依赖包&&启动服务
一.安装本地开发环境 1.安装本项目 在需要保存到本地的项目的文件夹,进入到文件夹里点击右键,bash here,出现下图: 2.安装依赖项目 3.安装依赖包(进入到命令行) # 安装依赖包 $ ...
- arcpy+PyQt+py2exe快速开发桌面端ArcGIS应用程序
前段时间有一个项目,大体是要做一个GIS数据处理工具. 一般的方法是基于ArcObjects来进行开发,因为我对ArcObjects不太熟悉,所以就思考有没有其他简单快速的方法来做. 在查看ArcGI ...
- DevExpress - 使用 GaugeControl 标尺组件制作抽奖程序 附源码
前不久,公司举办了15周年庆,其中添加了一个抽奖环节,要从在读学员中随机抽取幸运学员,当然,这个任务就分到了我这里. 最后的效果如下,启动有个欢迎页面,数据是来自Excel的,点击开始则上面的学号及姓 ...
- 万向节锁(Gimbal Lock)的理解
[TOC] 结论 我直接抛出结论: Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生. 他人解释 首先我们 ...
- LeetCode - Two Sum
Two Sum 題目連結 官網題目說明: 解法: 從給定的一組值內找出第一組兩數相加剛好等於給定的目標值,暴力解很簡單(只會這樣= =),兩個迴圈,只要找到相加的值就跳出. /// <summa ...
- photoshop:无法完成请求 因为暂存盘已满
今天photoshop打开一个问题,提醒:无法完成请求因为暂存盘已满 不用担心这个问题很好解决可能是你做的图比较大并不需要清理C盘空间 选择:编辑→首选项→暂存盘 设置第一暂存盘为D盘或E盘 总之 第 ...