zoukankan      html  css  js  c++  java
  • TransactionScope

    .NET Framework 2.0 版中新增的 TransactionScope 单独使用确实很方便。但是在实际项目中都有自己的访问层,如何才能和自己的数据访问层结合起来使用呢? 
               在项目中我是这样处理数据的:

      /// <summary>
        
    /// 外包业务访问类
        
    /// </summary>

        public class OutSourcingDAO
        
    {

            
    /// <summary>
            
    /// 增加
            
    /// </summary>
            
    /// <param name="bt"></param>
            
    /// <returns></returns>

            public int InsertGetIdentity(OutSourcing bt)
            
    {
                
    return new DAHelper(DataAccess.Create()).InsertGetIdentity(bt);
            }

            
    /// <summary>
            
    /// 更新
            
    /// </summary>
            
    /// <param name="bt"></param>
            
    /// <returns></returns>

            public int Update(OutSourcing bt)
            
    {
                
    return new DAHelper(DataAccess.Create()).Update(bt);
            }

            
    /// <summary>
            
    /// 删除
            
    /// </summary>
            
    /// <param name="bt"></param>
            
    /// <returns></returns>

            public int Delete(OutSourcing bt)
            
    {
                
    return new DAHelper(DataAccess.Create()).Delete(bt);
            }

        }

    上面 OutSourcing 为与表相对应的实体类 ;DAHelper 为作者自己实现的一个包装类,可以对任意实体进行增加,修改,删除 查询等功能。
      再贴一段代码:

       public int ExecSql(string strSql)
            
    {
                
    try
                
    {
                    
    this.OpenConnection();
                    cmd.CommandType 
    = CommandType.Text;
                    cmd.CommandText 
    = strSql;
                  
                   
    return cmd.ExecuteNonQuery();
                }

                
    catch (System.Exception e)
                
    {
                    
    throw this.CatchException(e);
                }

                
    finally
                
    {
                    
    this.CloseConnection();
                }

            }

    我最终通过调用 ExecSql  方法来与数据库交互,而该方法会自己打开数据库连接,执行语句,然后关闭连接。
    在操作同一个数据库的时候,如果要高效的使用 TransactionScope,必须保证 SqlConnection 不改变,即用同一个 SqlConnection 来完成所需要的增加
    删除,或修改。我想写这样的代码进行事务控制:

     public int UpdateTest(OutSourcing outSourcing, BusinessAccept businessAccept)
            
    {
                IDataAccess dac 
    = DataAccess.Create();
                DAHelper myHelper 
    = new DAHelper(dac);
                
    using (TransactionScope ts = new TransactionScope())
                
    {
                    myHelper.Update(outSourcing);
                    myHelper.Update(businessAccept);
                    
                    ts.Complete();
                }

            }

    这样就需要,执行第一个操作时候打开数据库连接,执行,不关闭连接,然后执行第二个操作,执行完关闭。显然,我想让 TransactionScope 
    实行 Dispose() 方法的时候关闭数据库连接。using 代码块的本质上等同于 try{}finally{} 语句代码块。为什么不封装一下 TransactionScope 让它满足自己的要求呢?

    /// <summary>
    /// TransactionScope 包装类
    /// </summary>

    public sealed class Scope : IDisposable
    {
        
    private TransactionScope m_TransactionScope = null;
        
    /// <summary>
        
    ///  测试访问类
        
    /// </summary>

        private DataAccessTest m_DataAccessTest = null;
        
    /// <summary>
        
    /// 实例化一个新的 TransactionScope
        
    /// </summary>
        
    /// <param name="dac"></param>

        public Scope(DataAccessTest dac)
        
    {
            
    this.m_DataAccessTest = dac;
            
    //告诉访问类 你已经使用了事务
            dac.SetScope(this);
            
    this.m_TransactionScope = new TransactionScope();

        }

        
    /// <summary>
        
    /// 发出事务结束命令
        
    /// </summary>

        public void Complete()
        
    {
            
    this.m_TransactionScope.Complete();
        }

        
    IDisposable 成员
    }


    数据库访问类代码如下:

    /// <summary>
    /// 模拟数据库访问类
    /// </summary>

    public class DataAccessTest
    {
        SqlConnection con 
    = null;
        SqlCommand cmd 
    = new SqlCommand();
        Scope scope 
    = null;
        
    string strCon = "这里是数据库连接字符串。。。。。";

        
    public void SetScope(Scope scope)
        
    {
            
    this.scope = scope;
        }

        
    private void OpenConnection()
        
    {

            
    if (con == null || scope == null)
            
    {
                con 
    = new SqlConnection(strCon);
                cmd.Connection 
    = con;
                con.Open();
                Console.WriteLine(
    " 打开数据库连接;");
            }

        }


        
    private void CloseConnection()
        
    {
            
    this.cmd.Parameters.Clear();
            
    if (scope == null)
            
    {
                
    // 
                con.Close();
                con.Dispose();
                Console.WriteLine(
    " 未使用事务 关闭数据库连接;");
            }

        }


        
    public int ExecuteSql(string strSql)
        
    {
            
    try
            
    {
                
    this.OpenConnection();
                cmd.CommandType 
    = CommandType.Text;
                cmd.CommandText 
    = strSql;
                Console.WriteLine(
    "执行 Sql 语句。。。");

                
    return cmd.ExecuteNonQuery();
            }

            
    catch (System.Exception e)
            
    {
                
    throw e;
            }

            
    finally
            
    {
                
    this.CloseConnection();
            }

        }

     
        
    public void Close()
        
    {
            con.Close();
            con.Dispose();
            Console.WriteLine(
    " 关闭数据库连接->该方法由 Scope中的Dispose()方法调用 ");
        }

    }

    赶快写个方法测试一下吧!

       /// <summary>
            
    /// 测试
            
    /// </summary>
            
    /// <param name="sender"></param>
            
    /// <param name="e"></param>

            private void button1_Click(object sender, EventArgs e)
            
    {
                
    try
                
    {
                    Console.WriteLine(
    "下面是使用事务的输出。。。。。。。。");
                    
    this.TestACT();
                    Console.WriteLine(
    "*********************下面是  未  使用事务的输出。。。。。。。。");
                    
    this.TestNoACT();
                }

                
    catch (System.Exception ex)
                
    {
                    Console.WriteLine(
    "出现了异常????????????");
                    MessageBox.Show(ex.ToString());
                }


            }

            
    /// <summary>
            
    /// 使用事务
            
    /// </summary>

            public void TestACT()
            
    {
                DataAccessTest dac 
    = new DataAccessTest();
                
    using (Scope scope = new Scope(dac))
                
    {
                    
    string strSql1 = "INSERT INTO [tilva20].[dbo].[T_Test]([TestName])VALUES('a')";
                    
    string strSql2 = "INSERT INTO [tilva20].[dbo].[T_Test]([TestName])VALUES('b')";
                    dac.ExecuteSql(strSql1);
                    dac.ExecuteSql(strSql2);

                    scope.Complete();
                }

            }

            
    /// <summary>
            
    /// 不使用事务
            
    /// </summary>

            public void TestNoACT()
            
    {
                    DataAccessTest dac 
    = new DataAccessTest();
             
                    
    string strSql1 = "INSERT INTO [tilva20].[dbo].[T_Test]([TestName])VALUES('a')";
                    
    string strSql2 = "INSERT INTO [tilva20].[dbo].[T_Test]([TestName])VALUES('b')";
                    dac.ExecuteSql(strSql1);
                    dac.ExecuteSql(strSql2);
            }



    查看一下输入的结果 
    下面是使用事务的输出。。。。。。。。
     打开数据库连接;
    执行 Sql 语句。。。
    执行 Sql 语句。。。
     关闭数据库连接->该方法由 Scope中的Dispose()方法调用 
    *********************下面是  未  使用事务的输出。。。。。。。。
     打开数据库连接;
    执行 Sql 语句。。。
     未使用事务 关闭数据库连接;
     打开数据库连接;
    执行 Sql 语句。。。
     未使用事务 关闭数据库连接
    ;

    输出结果和想像中的完全一样 数据库也正确(没任何原因不正确!)
    最后 改变一下方法:

       /// <summary>
            
    /// 使用事务
            
    /// </summary>

            public void TestACT()
            
    {
                DataAccessTest dac 
    = new DataAccessTest();
                
    using (Scope scope = new Scope(dac))
                
    {
                    
    string strSql1 = "INSERT INTO [tilva20].[dbo].[T_Test]([TestName])VALUES('a')";
                    
    string strSql2 = "INSERT INTO [tilva20].[dbo].[T_Test]([TestName])VALUES('b22222222222222222222222222222222222222222222222222222222222222222222222222222222222222')";
                    dac.ExecuteSql(strSql1);
                    dac.ExecuteSql(strSql2);

                    scope.Complete();
                }

            }

    熟悉数据库的肯定知道 “将截断字符串或二进制数据”吧!
    输出结果为:
     下面是使用事务的输出。。。。。。。。
     打开数据库连接;
    执行 Sql 语句。。。
    执行 Sql 语句。。。
     关闭数据库连接->该方法由 Scope中的Dispose()方法调用 
    出现了异常????????????
    数据库一条记录没有增加 数据库连接已经关闭  测试结果完全满意!
    对自己访问层稍做修改:
    最终的代码为:

       public int UpdateTest(OutSourcing outSourcing, BusinessAccept businessAccept)
            
    {
                IDataAccess dac 
    = DataAccess.Create();
                DAHelper myHelper 
    = new DAHelper(dac);
                
    using (Scope ts=new Scope())
                
    {
                    myHelper.Update(outSourcing);
                    myHelper.Update(businessAccept);
                    
                    ts.Complete();
                }

            }
  • 相关阅读:
    SEVERE: One or more listeners failed to start.
    springboot junit单元测试报错
    mybatis 日期查询datetime
    设计模式详解之程序设计六大原则
    非maven项目 idea project structure
    jdbcType DATE和TIMESTAMP区别
    mysql 保存23:59:59 自动加一秒
    1、在linux服务器centos虚拟机搭建nginx网站
    QRCode 生成二维码
    CSS3的calc()使用
  • 原文地址:https://www.cnblogs.com/YoungPop-Chen/p/3270867.html
Copyright © 2011-2022 走看看