EF版本:EF 5.0
IDE:VS2012
在Entity Framework中使用事务很简单,将操作放在TransactionScope中,并通过Complete()方法提交事务即可。
using (TransactionScope scope = new TransactionScope())
{
dal.Add(new SystemLogs() { Date = DateTime.Now });
dal.SaveChanges();
dal.Add(new SystemLogs());//Date为初始化值 0001/1/1 0:00:00
dal.SaveChanges();//这里会出发异常,不能正常保存数据 {"从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值。\r\n语句已终止。"}
//scope.Dispose(); //这个方法是释放事务scope
scope.Complete(); //这个方法是提交事务
}
以上代码中,使用了TransactionScope,执行后数据库结果如下:
这里我们可以看到,第一条数据成功保存,而第二条没有。
实事上,一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事务完成,它一般放在try{}的结尾处,不用判断前台操作是否成功,如果不成功,它会自己回滚。
正确的代码写法应该是:
using (TransactionScope scope = new TransactionScope())
{
try
{
dal.Add(new SystemLogs() { Date = DateTime.Now });
dal.SaveChanges();
dal.Add(new SystemLogs());//Date为初始化值 0001/1/1 0:00:00
dal.SaveChanges();//这里会触发异常,不能正常保存数据 {"从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值。\r\n语句已终止。"}
//触发异常,跳出try
scope.Complete(); //这个方法是提交事务
}
catch (Exception)
{
scope.Dispose(); //这个方法是释放事务scope
}
}
经过测试验证,在transaction.Complete()之前的代码中只要出现异常,事务就会回滚。
PS:
1.其实每一个Sql语句,每一个SaveChanges()都是一个单独的事务,执行失败则回滚并返回错误代码,执行成功则永久保存数据库。
2.在使用事务时,第一个SaveChanges()执行后,然后,sql server 就阻塞 锁定更新的表,导致访问受阻(无法查询等操作),使用TransactionScope,如果并发量大的话,容易并发引起死锁,造成TransactionScope出现异常。
其他参考:http://blog.csdn.net/yanwushu/article/details/10307801