最后,我们把提交语句修改为:
ctx.SubmitChanges(ConflictMode.FailOnFirstConflict);
表示第一次发生冲突的时候就不再继续了,然后并且去除最后的ctx.SubmitChanges();语句。来测试一下,在执行了SQL后再继续程序可以发现界面上只输出了数字1,说明在第一条记录失败后,后续的并发冲突就不再处理了。
事务处理
Linq to sql在提交更新的时候默认会创建事务,一部分修改发生错误的话其它修改也不会生效:
ctx.Customers.Add( new Customer { CustomerID = " abcdf " , CompanyName = " zhuye " });
ctx.Customers.Add( new Customer { CustomerID = " abcde " , CompanyName = " zhuye " });
ctx.SubmitChanges();
假设数据库中已经存在顾客ID为“abcde”的记录,那么第二次插入操作失败将会导致第一次的插入操作失效。执行程序后会得到一个异常,查询数据库发现“abcdf”这个顾客也没有插入到数据库中。
如果每次更新后直接提交修改,那么我们可以使用下面的方式做事务:
if (ctx.Connection != null ) ctx.Connection.Open();
DbTransaction tran = ctx.Connection.BeginTransaction();
ctx.Transaction = tran;
try
{
CreateCustomer( new Customer { CustomerID = " abcdf " , CompanyName = " zhuye " });
CreateCustomer( new Customer { CustomerID = " abcde " , CompanyName = " zhuye " });
tran.Commit();
}
catch
{
tran.Rollback();
}
private void CreateCustomer(Customer c)
{
ctx.Customers.Add(c);
ctx.SubmitChanges();
}
运行程序后发现增加顾客abcdf的操作并没有成功。或者,我们还可以通过TransactionScope实现事务:
using (TransactionScope scope = new TransactionScope())
{
CreateCustomer( new Customer { CustomerID = " abcdf " , CompanyName = " zhuye " });
CreateCustomer( new Customer { CustomerID = " abcde " , CompanyName = " zhuye " });
scope.Complete();
}
事务是一个原子的工作单位,必须完整的完成单位里的所有工作,要么全部执行,要么全部都不执行。如果提交事务,则事务执行成功;如果回滚事务,则事务执行失败。 事务具备4个基本特性--ACID(原子性、一致性、孤立性和持久性)。
在Linq to SQL中,有三种方法创建事务:
1. 如果没有指定任何事务,那么当调用SubmitChanges方法时,DataContext会默认创建一个事务。
2. 使用TransactionScope创建轻量级事务
3. 给DataContext的Transaction属性指定事务
下面我用代码分别来说明这几种创建事务的方法,以Northwind数据库为例,先来看看直接使用SubmitChanges:
NorthwindDataContext ctx = new NorthwindDataContext();
Customer c1 = new Customer { CustomerID = "TESTA",
CompanyName = "testa ' s company" };
Customer c2 = new Customer { CustomerID = "TESTBC",
CompanyName = "testb ' s company" }; ctx.Customers. Add (c1);
ctx.Customers. Add (c2); ctx.SubmitChanges();
上面这段代码中,先创建了两个Customer对象然后添加到DataContext里面,其中的c2的CustomerID赋值为"TESTBC",长 度为六个字符,而数据库中该字段约束为5个字符长度,这样在SubmitChanges的时候应该会有异常抛出。果然在执行的时候抛出了 SqlException,提示字符将被截断。