NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译
NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译
第一章第二节Mapping a class with XML
第一章第三节Creating class hierarchy mappings第一章第四节Mapping a one-to-many relationship第一章第五节Setting up a base entity class
Handling versioning and concurrency
版本控制和并发
在任何的多用户操作的系统中,为了处理并发更新以及版本问题,你必须在乐观并发控制和悲观并发控制中选择一种处理方式。在这一节中,我将给你展示怎样使用NHibernate去恰当地处理版本和乐观并发问题
准备工作
完成前面几节中的任务,包括Setting up a base entity class这节
如果去做
1.在Entity基类中,增加一个Version属性,代码如下所示:
public abstract class Entity<TId>
{
public virtual TId Id { get; protected set; }
protected virtual int Version { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as Entity<TId>);
}
2.在Product的映射文件中,增加version元素节点,name对应属性名称,代码如下所示:
<natural-id mutable="true">
<property name="Name" not-null="true" />
</natural-id>
<version name="Version" />
<property name="Description" />
<property name="UnitPrice" not-null="true" />
3. 在ActorRole映射文件中,也增加version元素节点
<id name="Id">
<generator class="guid.comb" />
</id>
<version name="Version" />
<property name="Actor" not-null="true" />
<property name="Role" not-null="true" />
分析原理
假如你有一个同时有两个用户操作数据库的应用程序,用户1和用户2同时获取相同的数据显示在他们的屏幕上,并且开始修改数据,用户1提交了他的修改后的数据至数据库中,一会儿,用户2也提交了他的修改后的数据。如果没有任何的并发访问检查,那么用户2的更新将会在不知不觉中覆盖了用户1的更新。这里有两个办法来防止这种情况的发生:乐观并发控制和悲观并发控制。
乐观并发控制的处理过程是这样的:当修改后的数据提交的时候,首先检查该数据是否已经被更新过。就上面的场景的来说,用户1和用户2开始修改他们的数据,用户1提交了他的修改后的数据,当用户2也提交了修改后的数据后,他的更新会是失败的,因为此时数据库中的该数据已经和用户2最初取得显示在屏幕上的数据已经不一致了。
下面的示例所示,我们有一个version字段来为一个实体跟踪这个更新的数据,Update如下所示:
UPDATE Product
SET Version = 2 /* @p0 */,
Name = 'Junk' /* @p1 */,
Description = 'Cool' /* @p2 */,
UnitPrice = 100 /* @p3 */
WHERE Id = '764de11e-1fd0-491e-8158-9db8015f9be5' /* @p4 */
AND Version = 1 /* @p5 */
NHibernate检查这个version的值是否和实体从数据库中加载数据时候的值是相同的,然后为该值加1,如果实体已经被更新过了,那么version字段的值不为1,并且该Update语句将不会更新任何行,NHibernate检测到该语句的更新结果返回的是0行记录就会抛出一个StaleStateException异常,意味着该实体的数据在内存中是过时的,不是最新的,已经和数据库失去了同步了。
补充知识
乐观并发控制之外的另一个选择就是使用悲观锁定。悲观锁定的过程是这样的:当一个用户获取数据的时候就给该数据加上一个独占锁,并且在他编辑该数据的时候也始终加上该独占锁,这样当用户1把数据显示在屏幕上进行编辑的时候,用户2就无法再获取同样的数据显示在屏幕上了。在上面的场景中,用户1取得数据,然后他拥有了对该数据的独占锁,用户2就无法再从数据库中读取该数据了。用户2的查询被阻塞,直至用户1释放了该独占锁或者查询超时。用户1在修改数据的时候不可避免地会有接听一个电话或者走开喝一杯咖啡的情况,这样的话将严重影响系统的并发访问。为了实现上述的悲观锁定,NHibernate需要你在应用程序事务中使用session.Lock。
乐观并发控制的其他方法
除了使用整形类型的version字段以外,NHibernate同样也允许我们使用基于DateTime类型的version字段。然而,Micorosoft SQL Server的datetime类型的精度为3毫秒,如果两个更新的提交非常的接近的话就会有问题了。最好是使用SQL Server 2008的 DateTime2日期类型,它拥有高达100纳秒的时间精度,或者也可以使用timestamp日期类型。
NHibernate也允许你使用传统的乐观并发控制的方式,可以通过设置optimistic-lock属性为dirty来实现,一个简单的示例看起来如下:
<class name="Product"
dynamic-update="true"
optimistic-lock="dirty">
在这种情况下,把Product对象的name从Stuff修改为Junk的SQL语句看起来如下所示:
UPDATE Product
SET Name = 'Junk' /* @p0 */
WHERE Id = '741bd189-78b5-400c-97bd-9db80159ef79' /* @p1 */
AND Name = 'Stuff' /* @p2 */
这就确保了用户读取数据后直到更新提交时Name的值没有被其他用户更新过(其他用户有可能已经更新过,如果已经更新过了,则上述SQL语句将不会更新任何行),然而,其他用户也可能已经更新了Product对象的其它字段的值了。
另外一个选择是设置optimistic-lock的值为all,这样设置以后,Product对象的自动产生的update语句看起来如下所示:
UPDATE Product
SET Name = 'Junk' /* @p0 */
WHERE Id = 'd3458d6e-fa28-4dcb-9130-9db8015cc5bb' /* @p1 */
AND Name = 'Stuff' /* @p2 */
AND Description = 'Cool' /* @p3 */
AND UnitPrice = 100 /* @p4 */
或许你已经猜到了,这种情况下,我们需要检验所有的属性的值,如果字段非常多的情况那是不太适合的。
当设置optimistic-lock的值为dirty时,dynamic-update的值必须设置为true。动态更新意味着update语句仅仅更新了变化了的属性值,而当dynamic-update设置为false时,update是在应用程序启动的时候就初始化了,它包含了实体的所有属性的值。
NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译的更多相关文章
- NHibernate.3.0.Cookbook第一章第五节Setting up a base entity class
Setting up a base entity class设置一个实体类的基类 在这节中,我将给你展示怎么样去为我们的实体类设置一个通用的基类. 准备工作 完成前面三节的任务 如何去做 1.在Ent ...
- 第一百一十六节,JavaScript,DOM操作样式
JavaScript,DOM操作样式 一.操作样式 CSS作为(X)HTML的辅助,可以增强页面的显示效果.但不是每个浏览器都能支持最新的CSS能力.CSS的能力和DOM级别密切相关,所以我们有必要检 ...
- 【PY从0到1】第六节 用户输入while循环
# 6 第六节 用户输入while循环 # 1> 重要的函数--input() # 我们先讲解一下input():当Python碰到input()后会执行括号内的语句. # 随后等待用户的输入. ...
- tensorflow2.0学习笔记第一章第四节
1.4神经网络实现鸢尾花分类 import tensorflow as tf from sklearn import datasets import pandas as pd import numpy ...
- (第一章第六部分)TensorFlow框架之实现线性回归小案例
系列博客链接: (一)TensorFlow框架介绍:https://www.cnblogs.com/kongweisi/p/11038395.html (二)TensorFlow框架之图与Tensor ...
- 第一章-第六题(帮人抢票,帮人选课这些软件是否合法 你怎么看?)--By梁旭晖
我觉得这些软件是合法的,符合道德规范的. 计算机当初设计的初衷就是简化甚至替代人类的工作.而软件作为计算机硬件的驱动着,其设计就是体现这些原则. 现在互联网上的订票,选课类型的网站还是有很多的,比如: ...
- tensorflow2.0学习笔记第一章第五节
1.5简单神经网络实现过程全览
- 第一百零六节,JavaScript变量作用域及内存
JavaScript变量作用域及内存 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只 ...
- Android开发训练之第五章第六节——Transferring Data Using Sync Adapters
Transferring Data Using Sync Adapters GET STARTED DEPENDENCIES AND PREREQUISITES Android 2.1 (API Le ...
随机推荐
- [iOS]XCODE5升级之路
1.Code Sign error: 解决方案:重新下载并安装Provisioning profile 2.错误:Undefined symbols for architecture armv ...
- UIImage 读取图片内存优化
在图片处理时,我们总会遇到一些内存优化的问题. 这里介绍的是其中一种内存优化处理方式. 场景: App 运行很卡,然后我用 Instruments 中的相关工具查看对象的内存占用情况,发现当图片加载 ...
- apt 之 最强技能:【欺骗】,文雅点【偷梁换柱】!
apt这种软件包管理系统,有个最大特点是:只照本宣科,而不管实际情况. 所以,我们用户就可以利用这一点,来欺骗它,达到我们的目的. ------------------------------好了,现 ...
- Windows 7 完美安装 Visual C++ 6.0
http://wenku.baidu.com/link?url=UiwoH2l4H_IWK6y8JkVNg4slp8gkM_9qudihP0XD4MdMCwm-j1-vINWEjQE1aBCeP121 ...
- IT运维队伍的管理
如何建设一支能够解决问题.创造价值.有活力的.不断进取的IT运维团队,并带领这支团队,充分发挥这个团队的优势力量,是运维业务有效开展的关键.运维 策略是直接体现运维业务的经济价值所在.好的运维措施.方 ...
- ActiveMQ的消息存储方式
1. 队列存储 采取先进先出模式,同一时间,消息只会发送给某一个消费者,只有当该消息被消费并告知已收到时,它才能在代理的存储中被删除. 对于持久性订阅来说,每一个消费者都会 ...
- mysql中,什么是视图,视图的作用是什么?
需求描述: 在看mysql的视图,对于视图的定义,进行基本的了解,在此记录下. 概念解释: 视图:存储的查询语句,当调用的时候,产生结果集,视图充当的是虚拟表的角色. 测试过程: 说明: 如果要对一张 ...
- 让Json更懂中文(JSON_UNESCAPED_UNICODE)
我们知道, 用PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, 类似”\u***”的格式, 还会在一定程度上增加传输的数据量. <?php echo json_ ...
- Laravel查询构造器简介
数据表 CREATE TABLE IF NOT EXISTS students( `id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(255) NO ...
- org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'parentId' in 'class java.lang.String'
Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ' ...