WSORM:为WSBLog写的简单ORM(五)
来源:互联网 发布:查淘宝优惠券的插件 编辑:程序博客网 时间:2024/04/29 18:59
我们说说数据库的并发控制问题,WSORM通过版本控制实现了乐观锁。
它的实现原理是什么样的呢?大家可以用“ORM 乐观锁”google一下,应该可以找到相应的文章。这里举例简述一下:
某银行系统的数据库中有一张“帐户表”,里面保存了“帐户余额”记录,我们在这个表中设计了一个整形的“Version”字段。
在读取帐户余额时,我们把版本号“Version”字段一同读取出来。在更新帐户余额时,比对刚才“已经读取出来的版本号”与“数据库中的最新版本号”,如果读取出来的版本号等于数据库中的版本号,则予以更新,否则报错。
举例说,A客户在银行柜台上从某帐户中提款,银行柜台的系统客户端读取账户余额为1000元,并连带读取出记录版本号为5;恰好此时,B客户在某地自动柜员机上也从同一帐户中取款,读取账号余额1000元,版本号也为5。
A客户取款500元后,账户余额应被更新为500。A客户这边的银行柜台系统客户端“在更新帐户余额的同时检查数据库中的记录版本号”,如果版本号仍为5,则将版本号加1,把版本号变更为6,同时更新帐户余额信息为500。
我们假设A客户这边首先取款成功,看看接下来B客户这边系统客户端的处理情况:
B客户领款后也要变更数据库,B客户这边的自动柜员机系统所取得的帐户余额记录其版本号为5,但“更新帐户记录的同时检查数据库中的记录版本号”,发现其已经被更新为6,放弃更新数据库。自动柜员机系统可以提示B客户取款失败,请客户重新进行取款操作。
怎么样才能在“在更新帐户余额的同时检查数据库中的记录版本号”,这里面有一个巧妙的方法,把“Version=已读取的版本号”作为更新条件对记录进行更新,如果更新影响的行数为0,则说明读取的版本已经过期,更新失败。
我们看看WSORM是怎么做的。
首先,我们在Northwind数据库的产品信息Products表中增加一个整形字段Version,不允许为Null,默认值为0。
然后修改类Product的定义,保证已经添加了Version这个Field,并且建立了和数据库中Version字段的映射信息:
...{
public static ObjectMap GetObjectMap()
...{
ObjectMap omap = new ObjectMap(typeof(Product),"Products");
omap.MemberMaps.Add("ID", "ProductID", DbFieldTypes.Int, MemberMapTypes.Identity);
omap.MemberMaps.Add("ProductName", "ProductName", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("SupplierID", "SupplierID", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("CategoryID", "CategoryID", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("QuantityPerUnit", "QuantityPerUnit", DbFieldTypes.String, MemberMapTypes.NormalField);
omap.MemberMaps.Add("UnitPrice", "UnitPrice", DbFieldTypes.Money, MemberMapTypes.NormalField);
omap.MemberMaps.Add("UnitsInStock", "UnitsInStock", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("UnitsOnOrder", "UnitsOnOrder", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("ReorderLevel", "ReorderLevel", DbFieldTypes.Int, MemberMapTypes.NormalField);
omap.MemberMaps.Add("Discontinued", "Discontinued", DbFieldTypes.Boolean, MemberMapTypes.NormalField);
//如果需要使用版本控制,需要在Products表中添加一个Version字段,Product添加一个Version成员,然后添加以下字段影射
omap.MemberMaps.Add("Version", "Version", DbFieldTypes.Int, MemberMapTypes.Version);
return omap;
}
public int ID;
public string ProductName;
public int SupplierID;
public int CategoryID;
public string QuantityPerUnit;
public decimal UnitPrice;
public int UnitsInStock;
public int UnitsOnOrder;
public int ReorderLevel;
public bool Discontinued;
public int Version;
public Product()
...{
}
}
我们写一个下面这样的测试函数,并且在代码中设置一个断点(见注释):
private void saveAndDeleteProductInfo()
...{
ISession session = this.northwindFactory.CreateSession();
Product product = new Product();
product.ProductName = "Outback Lager test--";
product.SupplierID = 7;
product.CategoryID = 1;
product.QuantityPerUnit = "24 - 355 ml bottles";
product.UnitPrice = 15.0000M;
product.UnitsInStock = 15;
product.UnitsOnOrder = 10;
product.ReorderLevel = 30;
product.Discontinued = false;
System.Diagnostics.Debug.WriteLine("==================================================");
session.Save(product);
session.Execute();
//注意,我们在下一句设置一个断点!
product.ProductName = "Outback Lager test----";
System.Diagnostics.Debug.WriteLine("==================================================");
session.Save(product);
session.Execute();
session.Delete(product);
session.Execute();
}
执行到断点处,Debug的输出如下:
insert into Products (ReorderLevel,Discontinued,CategoryID,ProductName,QuantityPerUnit,UnitsInStock,UnitsOnOrder,Version,UnitPrice,SupplierID) values (@ReorderLevel,@Discontinued,@CategoryID,@ProductName,@QuantityPerUnit,@UnitsInStock,@UnitsOnOrder,@Version,@UnitPrice,@SupplierID)
ReorderLevel : 30
Discontinued : False
CategoryID : 1
ProductName : Outback Lager test--
QuantityPerUnit : 24 - 355 ml bottles
UnitsInStock : 15
UnitsOnOrder : 10
Version : 0
UnitPrice : 15.0000
SupplierID : 7
我们在断点处停住,马上去检查一下数据库的Products表,发现记录确实已经成功添加到表中。
我们手工把新插入的记录的Version字段的值改为1。
继续执行代码,程序会抛出异常,Debug的输出如下:
==================================================
update Products set ProductName=@ProductName,Version=@Version where ProductID=110 and Version=0
ProductName : Outback Lager test----
Version : 1
未处理的“com.oucsoft.WSORM.WSORMException”类型的异常出现在 WSORM.exe 中。
——我们可以看到,WSBLog是将“where ProductID=110 and Version=0”作为update的条件。一旦发现update影响的行数为0,WSBLog就会回滚数据库事务,并且向上抛出异常。
- WSORM:为WSBLog写的简单ORM(五)
- WSORM:为WSBLog写的简单ORM(一)
- WSORM:为WSBLog写的简单ORM(二)
- WSORM:为WSBLog写的简单ORM(三)
- WSORM:为WSBLog写的简单ORM(四)
- WSORM:为WSBLog写的简单ORM(六)
- 为初学者写ORM,ORM的原理及测试案例
- 使用Java的反射简单的实现ORM框架(五)
- 为自己的C# ORM 写一个代码自动生成器
- 反射(五)ORM
- python写简单爬虫的五种方法 (转)
- (五)4 写个简单的LED驱动
- 最简单的ORM
- 自己动手写ORM的感受
- Odoo运行机制(五)--ORM
- 使用VB.Net写一个简单的数据访问层(不能称ORM):前言
- 使用VB.Net写一个简单的数据访问层(不能称ORM):CRUD操作
- 通过JAVA反射实现简单的ORM,将查询结果封装为对象
- 使用简单的Ajax Framework -MagicAjax.NET
- MMS封装
- 笔记:做一个高中分班的东西。
- VS2005如何进行单元测试
- PDA 中文的具体诠释
- WSORM:为WSBLog写的简单ORM(五)
- 新年来临最后一天听到了职业培训新的声音
- 几个Javascript函数
- Freebsd 6.0下安装支持SSL连接的MySQL 5.0
- Perl 的简单语法
- suse Linux中清空root 密码
- 关于VC6调试程序时显示Unicode字符串不全的问题
- Linux中关于重要配置文件
- 祝你新年快乐