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