ADO.Net2.0新的事务类型

事务

提起事务大家并不陌生,通俗点说就是一组操作要么都执行要么都不执行。这个在数据库操作方面用的特别多,因为我们知道数据库完整性特别重要。大家经常拿银行账务举例子:例如你从银行转账,由A账户转到B账户,要转一百万(O(∩_∩)O~,数据大点有说服力)。具体操作就是要从A账户扣除一百万在B账户增加一百万。可是就在刚从A账户扣除一百万之后停电了或者计算机死机了。这个时候很明显A少了一百万,但是对于B并没有加上。现在假设你拥有A账户,由于一笔生意要给对方B转一百万,现在怎么办?对方是不会承认受到钱的,你无缘无故少了一百万啊。事务的作用正在于此,如果中途停电之后,它就不会将A账户的钱扣除,也就是相当于没有执行"扣除—增加"这一组操作。

.Net1.1事务

在.Net1.1中要实现事务,也不是很复杂。我们看一段代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; namespace Net2Transaction { class Program { static void Main(string[] args) { SqlConnection sqlCon = new SqlConnection(); sqlCon.ConnectionString = "Data Source=.;Database=Northwind;Integrated Security=SSPI"; sqlCon.Open(); SqlTransaction sqlTra = sqlCon.BeginTransaction(); try { SqlCommand sqlCom = new SqlCommand(); sqlCom.Transaction = sqlTra; sqlCom.Connection = sqlCon; sqlCom.CommandText = "delete from orderdetails where orderid=@orderdetails_orderid"; sqlCom.Parameters.Add(new SqlParameter("@orderdetails_orderid", "11077")); sqlCom.ExecuteNonQuery(); sqlCom.CommandText = "delete from orders where orderid=@orders_orderid"; sqlCom.Parameters.Add(new SqlParameter("@orders_orderid", "11077")); sqlCom.ExecuteNonQuery(); sqlTra.Commit(); } catch (Exception ex) { sqlTra.Rollback(); } finally { sqlCon.Close(); sqlCon.Dispose(); } } } }

上面代码非常简单为了方便观察我们没有进行任何封转,就是为了完成删除订单编号为"11077"的订单及其明细。很明显某种情况下我们要是删除订单的同时就要删除其对应的明细,在这里这两个删除操作就是一组事务,因此在上面的代码中我们使用了.Net1.1中的事务,如果删除了明细(注意需要先删除明细再删除订单信息,因为有外键约束),在删除订单的时候发生异常也可以保证数据完整性。

.Net2.0事务

上面的例子中使用事务似乎不是太麻烦,功能也可以实现。但是如果我们在一个大型项目中直接出现这样的代码恐怕就不太好了,我们需要封装。可是如果封装数据库操作的时候如何对事务也进行封装呢?也就是我现在在DBHelper中有一个执行sql的方法,我想这个方法可以单独执行sql又可以在执行的时候启用事务。这个问题要想做不是不可以,但是问题是在这里每一个连接对应的事务和我们执行命令command对应的事务要一致,这样造成在封装类DBHeper中对连接的管理就比较麻烦了。再者,即便都做好了,在使用时也是比较麻烦,例如我再最近的一个项目中就有需求将三百多个sql命令在一个事务中实现,这种情况如果说用上面的方法直接写代码会很乱,因为这中间有许许多多其他操作,如果用DBHelper呢又显得笨重而没有好的方法来管理,而且不管用哪种都会发现我们会因为使用了事务而打乱原来的编程。怎么办呢?这就是.Net2.0新的事务机制。我们可以不必关系有了事务如何来编程,而在编写程序的时候可以按照正常的方式,然后只需要在需要事务管理的前后添加两句代码就可以完成事务的处理。而且这种方式我们可以在不同数据库连接中使用事务。太好了,不妨先看看上面的实现在用新的方式如何做吧:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; using System.Transactions; using Cmj.MyData; namespace Net2Transaction { class Program { static void Main(string[] args) { using (TransactionScope ts = new TransactionScope()) { try { DBHelper helper = new DBHelper(); Dictionary<string, object> para; para = new Dictionary<string, object>(); para.Add("orderdetails_orderid", "11075"); helper.ExcuteNonQuery(CommandType.Text, "delete from orderdetails where orderid=@orderdetails_orderid", para); para.Clear(); para.Add("orders_orderida", "11075"); helper.ExcuteNonQuery(CommandType.Text, "delete from orders where orderid=@orders_orderid", para); ts.Complete(); } catch (Exception ex) { throw ex; } } } } }

看起来是不是和原来不太一样,实质已经完全改变了(注意:这里用了封装的DBHelper,没有再去做创建连接这些操作)。变化在哪呢?我们看一下这幅图:

可以清楚地看到,业务机制完全是独立的,需要添加哪些操作到事务中,只需要在前后加上两句话即可实现。并且上面例子中heper.ExcuteNonQuery方法中封装了创建连接和关闭连接的操作,这就是说事务处理不再针对某个具体连接,就算中间再创建再多的连接也可以实现事务机制(注意对于多个连接联动事务将自动激活一个 MSDTC 管理的 Distributed Transaction[ 如果是一个连接的话要是使用 sql server2005 一起以上版本的话会 .Net 会自动创建一个 Local Transaction] ,所以必须启动 Distributed Transaction Coordinator 服务,怎么启动我就不用说了吧 )。从创建TransactionScope类的实例开始启动事务,直到Complete方法执行才提交事务,再这中间无论发生任何异常导致运行不到Complete方法,事务都会回滚(注意新的事务类在System.Transaction命名空间)。当然,这只是2.0事务部分一个小的应用,它还有更强大的功能我们还没有用到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值