12-8. 重新获取一个属性的原始值

问题

在实体保存到数据库之前,你想重新获取属性的原始值

解决方案

假设你有一个模型 (见 Figure 12-11) 表示一个员工( Employee),包含工资(salary)属性. 你有一个业务规则,规定一个员工的工资增长不能超过10%.在一个实体保存到数据库之前,你想验证这条规则,拿新的工资与原来的工资比较,看是否超过10%.

Figure 12-11. An Employee entity with the employee’s salary

为核实工资增长不超过10%,我们override SaveChanges 事件. 在该事件里,我们重新取得当前实体的原始值,如果新值超过原始值的10%,我们抛出一个异常,当然这个异常也会导致保存失败.

代码 Listing 12-8 展示了这些细节:

Listing 12-8. Overriding the SaveChanges Event to Enforce the Business Rule

class Program

{

static void Main(string[] args)

{

RunExample();

}

static void RunExample()

{

using (var context = new EFRecipesEntities())

{

var emp1 = new Employee { Name = "Roger Smith", Salary = 108000M };

var emp2 = new Employee { Name = "Jane Hall", Salary = 81500M };

context.Employees.Add(emp1);

context.Employees.Add(emp2);

context.SaveChanges();

emp1.Salary = emp1.Salary * 1.5M;

try

{

context.SaveChanges();

}

catch (Exception)

{

Console.WriteLine("Oops, tried to increase a salary too much!");

}

}

using (var context = new EFRecipesEntities())

{

Console.WriteLine();

Console.WriteLine("Employees");

foreach (var emp in context.Employees)

{

Console.WriteLine("{0} makes {1}/year", emp.Name,

emp.Salary.ToString("C"));

}

}

Console.WriteLine("Press any key to close...");

Console.ReadLine();

}

}

public partial class EFRecipesEntities

{

public override int SaveChanges()

{

var entries = this.ChangeTracker.Entries().Where(e => e.Entity is Employee && e.State ==

System.Data.Entity.EntityState.Modified);

foreach (var entry in entries)

{

var originalSalary = Convert.ToDecimal(

entry.OriginalValues["Salary"]);

var currentSalary = Convert.ToDecimal(

entry.CurrentValues["Salary"]);

if (originalSalary != currentSalary)

{

if (currentSalary > originalSalary * 1.1M)

throw new ApplicationException(

"Can't increase salary more than 10%");

}

}

return base.SaveChanges();

}

}

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

Oops, tried to increase a salary too much!

Employees

Roger Smith makes $108,000.00/year

Jane Hall makes $81,500.00/year

原理

在override  SaveChanges里, 我们先获取状态为modified 的Employee 实体,接着挨个查看它们的Salary 属性的原始值与当前值.如果二者不相等且超过10%,我们就抛出一个ApplicationException异常. 否则, 我们就简单地调用DbContext 的  SaveChanges ,让EF把修改保存到数据库.

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

Entity Framework 6 Recipes 2nd Edition(12-8)译 -> 重新获取一个属性的原始值的更多相关文章

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

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

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

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

  3. Entity Framework 6 Recipes 2nd Edition(12-7)译 -> 设定默认值

    12-7. 设定默认值 问题 在把一个实体保存到数据库之前,设置该实体属性的默认值 解决方案 假设你有一个如Figure 12-9所示的表, 它保存采购订单(purchase order). 主键Pu ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 学点HTTP知识

    不学无术 又一次感觉到不学无术,被人一问Http知识尽然一点也没答上来,丢人丢到家了啊.平时也看许多的技术文章,为什么到了关键时刻就答不上来呢? 确实发现一个问题,光看是没有用的,需要实践.看别人说的 ...

  2. .NET里简易实现AOP

    .NET里简易实现AOP 前言 在MVC的过滤器章节中对于过滤器的使用就是AOP的一个实现了吧,时常在工作学习中遇到AOP对于它的运用可以说是很熟练了,就是没想过如果自己来实现的话是怎么实现的,性子比 ...

  3. Android GridView 通过seletor 设置状态和默认状态

    Android中可以通过selector控制GridView Item 的状态,而省去使用代码控制 GridView View Selector Xml文件 <?xml version=&quo ...

  4. 如何进行python性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  5. SDWebImage源码解读之SDWebImageCache(上)

    第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...

  6. js面向对象学习 - 对象概念及创建对象

    原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...

  7. System.Guid ToString五中格式

    参考:https://msdn.microsoft.com/en-us/library/97af8hh4.aspx 测试代码: using System; using System.Collectio ...

  8. CocoaPods的安装、使用、以及遇到的问题

    CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,AFNetWorking等等.可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而 ...

  9. iOS中支付宝集成

    iOS中支付宝集成 如今各种的App中都使用了三方支付的功能,现在将我在使用支付宝支付集成过程的心得分享一下,希望对大家都能有所帮助 要集成一个支付宝支付过程的环境,大致需要: 1>公司:先与支 ...

  10. LVM基本介绍与常用命令

    一.LVM介绍LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制LVM - 优点:LVM通常用于装备大量磁盘的系统,但它同样适 ...