LinQ to SQL 并发与事务(1)


  首先使用下面的SQL语句查询数据库的产品表:

  
  
select * from products where categoryid = 1

  查询结果如下图:

  为了看起来清晰,我已经事先把所有分类为1产品的价格和库存修改为相同值了。然后执行下面的程序:

  
  
var query = from p in ctx.Products where p.CategoryID == 1 select p;
foreach (
var p in query)
p.UnitsInStock
= Convert .ToInt16(p.UnitsInStock - 1 );
ctx.SubmitChanges();
// 在这里设断点

  我们使用调试方式启动,由于设置了断点,程序并没有进行更新操作。此时,我们在数据库中运行下面的语句:

  
  
update products
set unitsinstock = unitsinstock - 2 , unitprice = unitprice + 1
where categoryid = 1

  然后在继续程序,会得到修改并发(乐观并发冲突)的异常,提示要修改的行不存在或者已经被改动。当客户端提交的修改对象自读取之后已经在数据库中发生改 动,就产生了修改并发。解决并发的包括两步,一是查明哪些对象发生并发,二是解决并发。如果你仅仅是希望更新时不考虑并发的话可以关闭相关列的更新验证, 这样在这些列上发生并发就不会出现异常:

  
  
[ Column(Storage="_UnitsInStock", DbType="SmallInt", UpdateCheck = UpdateCheck.Never) ]
[ Column(Storage="_UnitPrice", DbType="Money", UpdateCheck = UpdateCheck.Never) ]

  为这两列标注不需要进行更新检测。假设现在产品价格和库存分别是27和32。那么,我们启动程序(设置端点),然后运行UPDATE语句,把价格+1,库 存-2,然后价格和库存分别为28和30了,继续程序可以发现价格和库存分别是28和 31。价格+1是之前更新的功劳,库存最终是-1是我们程序之后更新的功劳。当在同一个字段上(库存)发生并发冲突的时候,默认是最后的那次更新获胜。

  解决并发

  如果你希望自己处理并发的话可以把前面对列的定义修改先改回来,看下面的例子:

  
  
var query = from p in ctx.Products where p.CategoryID == 1 select p;
foreach (var p in query)
p.UnitsInStock
= Convert.ToInt16(p.UnitsInStock - 1 );
try
{
ctx.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException)
{
foreach (ObjectChangeConflict cc in ctx.ChangeConflicts)
{
Product p
= (Product)cc.Object;
Response.Write(p.ProductID
+ " <br/> " );
cc.Resolve(RefreshMode.OverwriteCurrentValues);
// 放弃当前更新,所有更新以原先更新为准
}
}
ctx.SubmitChanges();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值