12定制EF

在本章的小节里,定制实体对象和EF处理的一些功能.这些小节将涵盖很多”幕后”的事情,能让你的代码更加统一解决一些事情,比如用一个业务规则中心统一地为实体执行验证.

本章开始的小节,将演示如何在你的应用程序中当调用SaveChanges() 时,执行你自己的代码. 如果你想在你的应用程序里单独定制业务规则,本小节和有些小节非常有用.

在其它小节里,我们将演示如何跟踪数据库连接,如果自动报告集合的改变,如何实现级联删除,如何设定默认值,和如何与强类型的XML属性一起使用.所有这些定制共同点就是扩展对象和EF处理过程使你的代码更具弹性,统一性和可维护性.

12-1. 当SaveChanges( ) 被调用时执行你的代码

问题

你想在data context 中SaveChanges()被调用时,执行你的代码

解决方案

假设你有一个关于申请人的模型(如Figure 12-1所示). 申请人文档做为模型的一部分,你想在Applicant被删除时,文档也一起删除.你可能发现在你应用程序的每个删除Applicant地方,都要删除文档,而你想用一个统一的方式来处理

Listing 12-1. Overriding SaveChanges() to Delete the Resume File When the Applicant Is Deleted

为确保文档随同applicant一起删除, 我们在DbContext 里override SavingChanges() 方法, 我们需要先浏览DbContext里的实体,找出要被删除的Applicant,然后调用真正的SaveChanges() 方法. 最后,为每个被删除的Applicant删除文件,代码如Listing 12-1所示:

Listing 12-1. Overriding SaveChanges() to Delete the Resume File When the Applicant Is Deleted

class Program

{

static void Main(string[] args)

{

using (var context = new EFRecipesEntities())

{

var path1 = "AlexJones.txt";

File.AppendAllText(path1, "Alex Jones\nResume\n...");

var path2 = "JanisRogers.txt";

File.AppendAllText(path2, "Janis Rodgers\nResume\n...");

var app1 = new Applicant

{

Name = "Alex Jones",

ResumePath = path1

};

var app2 = new Applicant

{

Name = "Janis Rogers",

ResumePath = path2

};

context.Applicants.Add(app1);

context.Applicants.Add(app2);

context.SaveChanges();

//删除 Alex Jones

context.Applicants.Remove(app1);

context.SaveChanges();

}

}

}

public partial class EFRecipesEntities

{

public override int SaveChanges()

{

Console.WriteLine("Saving Changes...");

var applicants = this.ChangeTracker.Entries().Where(e => e.State == System.Data.Entity.EntityState.Deleted)

.Select(e => e.Entity).OfType<Applicant>().ToList();

int changes= base.SaveChanges();

Console.WriteLine("\n{0} applicants deleted",applicants.Count().ToString());

foreach (var app in applicants)

{

File.Delete(app.ResumePath);

Console.WriteLine("\n{0}'s resume at {1} deleted",app.Name, app.ResumePath);

}

return changes;

}

}

上述Listing 12-1代码输出结果如下:

Saving Changes...

0 applicants deleted

Saving Changes...

1 applicants deleted

Alex Jones's resume at AlexJones.txt deleted

原理

Listing 12-1里的代码,先插入两个applicant同时创建他们各自的文档.我们的目标是用统一的方式,当applicant被删除时,他们的文档也一同被删除.我们通过override SaveChanges() 方法来实现.在我们的 SaveChanges() 方法中,首先收集所有将被删除的Applicant实例, 接着我们调用真正的

SaveChanges() 方法,把它们从数据库中删除,最后在遍历我们最开始收集的实例,在遍历里删除他们各自的文档. 因为实体从数据库删除后,也会在context中删除,我们不能再通过查询找到context中被删除的裸体,所以第一步里我们用了ToList()方法,先把要被删除的实体保存到另一个对象中.

EF没有实体的插入,更新,修改事件,但是很多想在这些事件里处理的事情,都可以像我们这里的方式一样,通过override SaveChanges() 方法实现.

附:创建示例用到的数据库的脚本文件

Entity Framework 6 Recipes 2nd Edition(12-1)译 -> 当SaveChanges( ) 被调用时执行你的代码的更多相关文章

  1. Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新

    因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...

  2. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  3. Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪

    9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...

  4. Entity Framework 6 Recipes 2nd Edition(13-4)译 -> 有效地创建一个搜索查询

    问题 你想用LINQ写一个搜索查询,能被转换成更有效率的SQL.另外,你想用EF的CodeFirst方式实现. 解决方案 假设你有如下Figure 13-6所示的模型 Figure 13-6. A s ...

  5. Entity Framework 6 Recipes 2nd Edition(13-9)译 -> 避免Include

    问题 你想不用Include()方法,立即加载一下相关的集合,并想通过EF的CodeFirst方式实现. 解决方案 假设你有一个如Figure 13-14所示的模型: Figure 13-14. A ...

  6. Entity Framework 6 Recipes 2nd Edition(目录索引)

    Chapter01. Getting Started with Entity Framework / 实体框架入门 1-1. A Brief Tour of the Entity Framework ...

  7. Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体

    第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...

  8. Entity Framework 6 Recipes 2nd Edition(13-2)译 -> 用实体键获取一个单独的实体

    问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Paint ...

  9. Entity Framework 6 Recipes 2nd Edition(13-3)译 -> 为一个只读的访问获取实体

    问题 你想有效地获取只是用来显示不会更新的操作的实体.另外,你想用CodeFirst的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种 ...

随机推荐

  1. Apache执行Python脚本

    由于经常需要到服务器上执行些命令,有些命令懒得敲,就准备写点脚本直接浏览器调用就好了,比如这样: 因为线上有现成的Apache,就直接放它里面了,当然访问安全要设置,我似乎别的随笔里写了安全问题,这里 ...

  2. 通过一个demo了解Redux

    TodoList小demo 效果展示 项目地址 (单向)数据流 数据流是我们的行为与响应的抽象:使用数据流能帮我们明确了行为对应的响应,这和react的状态可预测的思想是不谋而合的. 常见的数据流框架 ...

  3. Java中的多态

    1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal {public abstract void Say();} 子类: public class ...

  4. Angular企业级开发-AngularJS1.x学习路径

    博客目录 有链接的表明已经完成了,其他的正在建设中. 1.AngularJS简介 2.搭建Angular开发环境 3.Angular MVC实现 4.[Angular项目目录结构] 5.[SPA介绍] ...

  5. UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?

    选择SQLite的理由 在做UWP开发的时候我们首选的本地数据库一般都是Sqlite,我以前也不知道为啥?后来仔细研究了一下也是有原因的: 1,微软做的UWP应用大部分也是用Sqlite.或者说是微软 ...

  6. angular 源码分析 1 - angularInit()

    angularjs 是个神奇的框架,由于我的好奇,想了解她的内部工作原理,只能一步一步的走进她,靠近她,和她深入的交流. angularjs 的入口是什么样子的呢?一起掀起她的盖头吧. 在这里我只讲方 ...

  7. Discuz NT 架构剖析之Config机制

    接触了Discuz NT! 一段时间了,是时候做个总结了,标题好霸气,有木有? 都是托园子里的大牛代振军的福啊,哈哈哈哈. 首先论坛的信息不是完全存储在数据库里面的,一部分信息存储在config文件里 ...

  8. ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存

    ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 part 1:给我点时间,允许我感慨一下2016年 正好有时间,总结一下最近使用的一些技术,也算是为2016年画上一个完 ...

  9. 火星坐标、百度坐标、WGS-84坐标相互转换及墨卡托投影坐标转经纬度JavaScript版

    火星坐标 火星坐标是国家测绘局为了国家安全在原始坐标的基础上进行偏移得到的坐标,基本国内的电子地图.导航设备都是采用的这一坐标系或在这一坐标的基础上进行二次加密得到的.火星坐标的真实名称应该是GCJ- ...

  10. [数据结构]——堆(Heap)、堆排序和TopK

    堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...