zoukankan      html  css  js  c++  java
  • ADO.NET在C#环境中的事务Transaction示例

    为图方便省事,你可以在一个Command对象的CommandText属性指定多条以;分割的语句。这种情况下若没有事务,所有的语句都会被执行,若其中有语句出错,就导致了数据的不一致性。

    当然我们也可以写存储过程,在SQLServer的数据库系统内建存储过程的语句若没有事务,多条语句中的部分语句失效,一样导致数据的不一致性:你可以在存储过程内部Try/Catch/BeginTransaction等。

     Connection对象BeginTransaction启动事务,然后将事务赋值给Command对象的Transaction属性即挂接了事务。即使没有Commit 和Rollback,若执行中出现错误,事务一样自动回滚,或者成功提交。

    BeginTransaction可以指定隔离级别。ReadXXX不会对数据库加锁,尽管在事务中,外部程序仍然可以读取数据;但若事务中有Update语句,将导致数据库锁,外部程序不能继续读取数据。

    尽量考虑在存储过程中使用事务,避免使用ADO的事务,因为ADO的事务可能导致数据库长时间处于锁定状态;而数据库内的存储过程中的事务往往不会长时间挂起事务。

    下面是简单的示例,供参考:

            /// <summary>
            
    /// ADO事物处理:单一Command对象执行多条语句:
            
    /// 包括导致异常的语句的后续语句,都将被执行,若没有Transaction,修改为15。
            
    /// </summary>
            private static void TransByADO()
            {
                
    string connect = "Data Source=.\\sqlexpress; Initial Catalog=NorthWind ; Integrated Security = true;";
                
    //Old value: UnitPrice=18
                string update = "Update Northwind.dbo.Products set UnitPrice=10 where ProductID=1;";
                update 
    += "update Products set unitPrice=unitprice-18 where productID=1;"//因CHECK约束,将失败
                update += "update Products set unitPrice=15 where productID=1";

                SqlTransaction tranProducts 
    = null;

                
    using (SqlConnection cnNorthwind = new SqlConnection(connect))
                {
                    
    try
                    {

                        cnNorthwind.Open();
                        tranProducts 
    = cnNorthwind.BeginTransaction();//--1

                        SqlCommand cmdUpdate 
    = new SqlCommand(update, cnNorthwind);
                        cmdUpdate.Transaction 
    = tranProducts;//-2
                        cmdUpdate.ExecuteNonQuery();
                        
    //如果没有Commit()和Rollback(),事物仍然生效,结果为原始值18
                        tranProducts.Commit(); //--3
                    }
                    
    catch (SqlException ex)
                    {
                        tranProducts.Rollback();
    //--4
                        
    //throw ex;
                        Console.WriteLine(ex);
                    }
                    
    finally
                    {
                        cnNorthwind.Close();
                    }
                }

            }


            /// <summary>
            
    /// 存储过程中若有部分语句执行失败,在没有Transaction的情况下将导致数据不一致。
            //create procedure TransTest
            
    //as
            
    //begin
            
    //    update Products set unitPrice=10 where productID=1
            
    //    update Products set unitPrice=unitprice-18 where productID=1 
            
    //    update Products set unitPrice=15 where productID=1
            
    //end
            
    //go
            /// </summary>
            private static void TransByStoreProcedure()
            {
                
    string connect = "Data Source=.\\sqlexpress; Initial Catalog=NorthWind ; Integrated Security = true;";
                
    using (SqlConnection cnNorthwind = new SqlConnection(connect))
                {


                    SqlTransaction tranProducts 
    = null;

                    
    try
                    {
                        cnNorthwind.Open();
                        tranProducts 
    = cnNorthwind.BeginTransaction();//-----1

                        SqlCommand cmdProduct 
    = new SqlCommand("TransTest", cnNorthwind);
                        cmdProduct.CommandType 
    = CommandType.StoredProcedure;
                        cmdProduct.Transaction 
    = tranProducts;    //----2
                        cmdProduct.ExecuteNonQuery();
                        
    //如果没有Commit()和Rollback(),事物仍然生效,结果为原始值18
                        tranProducts.Commit();  //----3
                    }
                    
    catch (SqlException ex)
                    {
                        tranProducts.Rollback();  
    //----4
                        Console.WriteLine(ex.ToString());
                        
    //throw ex ;
                    }
                    
    finally
                    {
                        cnNorthwind.Dispose();
                    }
                }
            }
            /// <summary>
            
    /// BeginTransaction(IsolationLevel)定义事务的隔离级别
            
    /// ReadCommitted:默认项,读取时加共享锁,避免脏读,数据在事务完成前可修改,可被外部读取
            
    /// ReadUncommitted:可脏读,不发布共享锁,也无独占锁
            
    /// </summary>
            private static void TransDebug()
            {
                
    string connect = "Data Source=.\\sqlexpress; Initial Catalog=NorthWind ; Integrated Security = true;";
                
    using (SqlConnection cnNorthwind = new SqlConnection(connect))
                {
                    SqlCommand cmdProducts 
    = null;
                    SqlTransaction tranDebug 
    = null;
                    
    try
                    {
                        cnNorthwind.Open();
                        tranDebug 
    = cnNorthwind.BeginTransaction(IsolationLevel.ReadUncommitted);//可读未提交数据
                        cmdProducts = new SqlCommand("select * from products where ProductID=1", cnNorthwind);
                        cmdProducts.Transaction 
    = tranDebug;
                        cmdProducts.ExecuteNonQuery();

                        
    //下面行下断点,在MSMS查看数据记录是否可修改,并尝试修改:发现能修改数据
                        cmdProducts.CommandText = "Update products set UnitPrice=UnitPrice-18 where ProductID=1";
                        cmdProducts.ExecuteNonQuery();
                        
    //下面行下断点,因上面的Update导致数据被锁,无法在MSMS环境查看和修改数据
                        cmdProducts.CommandText = "select * from products where ProductID=1";
                        cmdProducts.ExecuteNonQuery();
                        
    //下面行下断点,发现仍无法读取数据,因为前面的Update已经锁定记录
                        throw new Exception("Rollback()");
                        tranDebug.Commit();
                    }
                    
    catch (SqlException ex)
                    {
                        tranDebug.Rollback();
                        Console.Write(ex.Message);
                        
    //throw;
                    }
                    
    finally
                    {
                        cnNorthwind.Dispose();
                    }
                }
            }
  • 相关阅读:
    Struts2操作request、session和application对象
    json工具性能比较:json-lib和jackson进行Java对象到json字符串序列化[转]
    Java中的内部接口
    Struts2.0 xml文件的配置(package,namespace,action)
    过滤器实用案例
    Struts2教程
    struts全包导入问题
    Maven构建项目速度太慢的解决办法 Maven 调试
    HBase之五:hbase的region分区
    HBase之二:Hbase优化
  • 原文地址:https://www.cnblogs.com/flaaash/p/2007259.html
Copyright © 2011-2022 走看看