开放式并发处理
在检测到并发冲突后,DataContext将抛出ChangeConfilictException,通过对异常的处理,用户可以决定如何处理并发冲突。下面代码示例了发生Optimistic Concurrency的情况:
01 var contextA = GenerateContext();
02 // 用contextB来模拟另外一个用户更新
03 var contextB = GenerateContext();
04
05 var customerA = contextA.Customers.First();
06 customerA.CompanyName = "Updating Value from A";
07 var customerB = contextB.Customers
08 .Where(c => c.CustomerID == customerA.CustomerID).Single();
09 customerB.CompanyName = "Updating Value from B";
10 contextB.SubmitChanges();
11
12 try
13 {
14 // 发生开放式冲突
15 contextA.SubmitChanges();
16 }
17 catch (ChangeConflictException)
18 {
19 // 在此添加代码处理冲突
20 }
由于customerA和customerB都是指向数据库的同一条数据,在contextB.SubmitChanges提交后,contextA.SubmitChanges就发生了冲突。
参考资料:
如何检测和解决提交冲突
http://msdn.microsoft.com/zh-cn/library/bb387001.aspx
下面我们接着讨论事务处理。在我们没有显式的开启事务时,DataContext.SubmitChanges在提交时会隐式创建事务,我们看看下面这段代码:
01 var context = GenerateContext();
02 Customer customerA = new Customer { CustomerID = "K.K" };
03 Customer customerB = new Customer { CustomerID = "K.K" };
04 context.Customers.InsertOnSubmit(customerA);
05 context.Customers.InsertOnSubmit(customerB);
06
07 try
08 {
09 context.SubmitChanges();
10 }
11 catch (Exception)
12 {
13 Console.WriteLine(context.Customers.Where(c => c.CustomerID == "K.K").Count()); // 输出0
14 }
由于customerA和customerB的CustomerID赋值相同,造成了Primary Key的冲突,所以customerB插入失败。但由于DataContext.SubmitChanges自动创建事务,所以customerB插入失败造成全部操作回滚,customerA也没有插入。