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 ...
随机推荐
- 【WP8】Uri关联启动第三方App
在WP8中支持启动第三方应用程序,比如在App1中可以打开App2,你可以在你的应用程序中直接打开QQ,也可以让其他开发者调用你的APP,例如:软件盒子 下面演示被调用方和调用方的使用方法,新建两个项 ...
- Single Pattern(单例模式)
单例模式是一种常用的软件设计模式.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的实例只能存在一个,单例模式是最好的 ...
- asp.net mvc maproute定义可变数量的自定义片断变量
有时候我们定义了如{controller}/{action}/{id}之类的路由规则,但是后面还可能跟上一堆可能会有可能不会有,但是路由规则是一样的,如{controller}/{action}/{i ...
- 解决win8.1电脑无法安装手机驱动问题
相信安装过win8.1的朋友都会有个问题,那就是自己的安卓手机怎么都连不上电脑,比如360助手.豌豆荚.91助手,都安不上驱动.下面几个简单步骤即可轻松解决. 1.首先声明,官方的驱动是完全支持win ...
- [原]unity3D bug记录
1.u3d 发出的xcode工程 崩溃出现这种信息 Display::DisplayLinkItem::dispatch() 到AppController.mm 修改成这样 - (void) Repa ...
- MTK 强制横屏
frameworks\base\policy\src\com\android\internal\policy\impl目录下的PhoneWindowManager.java的rotationForOr ...
- IOS 应用官方接口地址
地址: http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-a ...
- 7 -- Spring的基本用法 -- 7... 创建Bean的3种方式
7.7 创建Bean的3种方式 ① 调用构造器创建Bean. ② 调用静态工厂方法创建Bean. ③ 调用实例工厂方法创建Bean. 7.7.1 使用构造器创建Bean实例. 使用构造器来创建Bean ...
- 8 -- 深入使用Spring -- 3...1 Resource实现类UrlResource
8.3.1 Resource 实现类------UrlResource : 访问网络资源的实现类 1.访问网络资源 访问网络资源通过UrlResource 类实现,UrlResource是java.n ...
- CouchDB 未授权访问漏洞
0x00 CouchDB安装 CouchDB官方网站:http://couchdb.apache.org/ 一路Next直到完成安装,打开浏览器并访问以下链接:http://127.0.0.1:598 ...