SqlServer中的事务使用

一、事务的概念和特点

  事务(transaction)是恢复和并发控制的基本单位。

事务的特点

  原子性:事务是一个工作单元,要都成功,要么的失败
    例子:A付款给B,A余额-100,B余额+100,只能都成功或者都失败,不能把A的钱扣了,而B的没加上
  一致性:必须让数据库从一个一致状态到另一个一致状态
    例子:还是上边的例子,A和B的总余额没有改变(保持了一致性)
  隔离性:事务之间互不影响,并发执行的事务之间互不干扰(通过锁来实现的)
    例子:A给B付款 和 C给B付款是两个事务,A付A的,C付C的,互不干扰。
  持久性:事务对数据的改变时永久性的。
    例子:A付款后,A的余额确实少了100,B的余额多了100(数据库中的记录确实改变了)

二、事务的使用

还是用付款的例子,先添加以下测试数据

--创建一个账户表,添加约束,余额(money)不小于零
    create table Tb_bankAcount(
        Id int identity(1,1) primary key,
        Name nvarchar(20) not null,
        Money int not null
    )
    alter table Tb_bankAcount
    add constraint CK_money CHECK(money>=0) 
    --添加数据
    insert into Tb_bankAcount values('A',200)
    insert into Tb_bankAcount values('B',200)

2.1  sql中使用事务

begin transaction --开启事务
    declare @errorCount int=0;--记录错误的变量
        update Tb_bankAcount set Money-=500 where Name='A'
        set @errorCount+=@@ERROR
        update Tb_bankAcount set Money+=500 where Name='B'
        set @errorCount+=@@ERROR
    
    if @errorCount>0      --有错误就回滚
        rollback transaction
    else                  --没有错误提交
        commit transaction

  上边的代码执行时A用户的余额为200-500=-300,由于不满足约束条件(Money>0),执行回滚

2.2  Ado.Net中使用事务(SqlTransaction形式)

 1  using (SqlConnection conn = new SqlConnection(connStr))
 2             {
 3                 //要执行的sql脚本
 4                 string sqlText = @"update Tb_bankAcount set Money-=100 where Name='A'
 5         update Tb_bankAcount set Money+=100 where Name='B'";
 6                 conn.Open();
 7                 //创建事务
 8                 SqlTransaction tran = conn.BeginTransaction();
 9                 using (SqlCommand com = new SqlCommand(sqlText, conn))
10                 {
11                     try
12                     {
13                         //开启事务
14                         com.Transaction = tran;
15                         com.ExecuteNonQuery();
16                         //提交事务
17                         tran.Commit();
18                         Console.WriteLine("事务执行成功");
19                     }
20                     catch (Exception ex)
21                     {
22                         //回滚事务
23                         tran.Rollback();
24                         Console.WriteLine(ex.Message);
25                     }
26                 }
27             }

  上边的代码执行时,由于满足约束条件(Money>0),执行事务提交。

使用SqlTransaction执行事务时,每个事务都是基于SqlConnection的,如果我们的事务要跨越多个程序集或者使用多个数据库时,使用SqlTransaction来实现事务就比较麻烦了,针对这个问题.net 2.0出现了TransactionScope

2.3  Ado.Net中使用分布式事务(TransactionScope形式)

        static void Main(string[] args)
        {
            //连接字符串
            string connstr1 = @"your connctionString1";
            string connstr2 = @"your connctionString2";
           
            using (TransactionScope ts = new TransactionScope())
            {
                #region 执行任务1
                using (SqlConnection conn1 = new SqlConnection(connstr1))
                {
                    using (SqlCommand com = conn1.CreateCommand())
                    {
                        conn1.Open();
                        com.CommandText = "delete from t_stu where id=10";
                        com.ExecuteNonQuery();
                    }
                } 
                #endregion

                #region 执行任务2
                using (SqlConnection conn2 = new SqlConnection(connstr2))
                {
                    using (SqlCommand com = conn2.CreateCommand())
                    {
                        conn2.Open();
                        com.CommandText = "insert into t_stu(stuname,age) values ('zs',22')";
                        com.ExecuteNonQuery();
                    }
                }
                #endregion
                //通过ts.Complete()方法进行提交
                ts.Complete();
            }
        }

  上边的代码十分简单,我们可以看到使用TransactionScope可以轻松的构建分布式的事务模型,conn1和conn2两个连接可以连接不同的数据库。TransactionScope实现了IDispose()接口,我们可以使用using语法糖来自动释放资源。执行TransactionScope时会依此执行TranactionScope的所有代码,当执行到ts.Complete()时表示事务中的任务都执行完成了,进行提交。如果不显示地执行ts.Complete()方法,TransactionScope中代码执行完毕后执行回滚操作。

  事务在数据库和业务编码中十分重要,这里只是简单地介绍了.net平台下事务的基本用法,如果有不合理的地方,欢迎指出。

 

posted @ 2018-05-16 16:35  捞月亮的猴子  阅读(698)  评论(0编辑  收藏  举报