zoukankan      html  css  js  c++  java
  • 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平台下事务的基本用法,如果有不合理的地方,欢迎指出。

  • 相关阅读:
    geowebcache发布 arcgis 瓦片
    BLANK
    基于 SpringBoot 高仿某度网盘项目,前后端分离(含源码)
    基于SpringBoot+WebMagic实现一个的爬虫框架
    博客园主题
    vue el 自动计算时间加1天
    python报警告qt.gtimg.cn
    量化交易日志
    mybatis 一对多。对多对
    DBeaver执行SQL脚本,导入导出
  • 原文地址:https://www.cnblogs.com/wyy1234/p/9046701.html
Copyright © 2011-2022 走看看