TransactionScope应用

TransactionScope应用.NETFramework2.0版中新增的TransactionScope单独使用确实很方便。但是在实际项目中都有自己的访问层,如何才能和自己的数据访问层结合起来使用呢?          在项目中我是这样处理数据的: /**////   ///外包业务访问类   ///   publicclassOutSourcingDAO   {       /**

大家好,又见面了,我是你们的朋友全栈君。

.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 成员#region IDisposable 成员
    /** <summary>
    /// 当执行该方法的时候完成两件任务
    /// 1 关闭数据库连接
    /// 2 调用 TransactionScope 的 Dispose()方法
    /// </summary>
    void IDisposable.Dispose()
    {

        try
        {

            m_DataAccessTest.Close();
        }
        finally
        {

            m_TransactionScope.Dispose();
        }
    }

    #endregion
}

数据库访问类代码如下:

/** <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();
            }
        }

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/logicbiz/archive/2008/04/23/2317712.aspx

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161948.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux系统dpkg命令[通俗易懂]

    linux系统dpkg命令[通俗易懂]dpkg是Debianpackage的简写,为”Debian“操作系统专门开发的套件管理系统,用于软件的安装,更新和移除。阅读目录安装软件 列出与该包先关联的文件 显示包的版本 移除软件(保留配置) 移除软件(不保留配置) 查找包的详细信息 列出deb包的内容安装软件命令:dpkg-i<.debfilename>实例:dpkg-i~/Download/mozybackup_i386.debmozybackup_i386.deb是手动下…

    2022年5月11日
    49
  • Android preference_android:orientation=”vertical”

    Android preference_android:orientation=”vertical”【正文】一、PreferenceFragment的引入:PreferenceActivity是一个非常有用的基类,当我们开发Android项目时避免不了选项设置,这些设置习惯用Preference来保存。Android专门为这种Activity提供了便捷的基类PreferenceActivity。如果继承自Preference则不需要自己控制Preference的读写,Preference

    2025年9月27日
    3
  • tomcat打印日志乱码,入库数据正常_tomcat输出日志乱码

    tomcat打印日志乱码,入库数据正常_tomcat输出日志乱码Tomcat后台日志乱码问题文章目录Tomcat后台日志乱码问题一、找到乱码原因二、Tomcat端乱码处理三、IDEA端设置小结一、找到乱码原因  基本上我们安装的windows系统本地语言都是中文,用的是GBK编码,而我们IDEA和Tomcat日志选择的是utf8编码,因此编码方式不一致造成了我们的中文乱码问题。二、Tomcat端乱码处理  既然原因已经找到了,接着就是解决问题了,分别设置IDEA和Tomcat的编码就ok了。先对Tomcat进行处理,如下:  1.找到Tomcat的安装目录

    2022年9月26日
    1
  • 交互式查询

    交互式查询1 nbsp OLAP 和 OLTP 的特点 nbsp nbsp nbsp OLAP 联机分析处理 nbsp 和 OLTP 联机事务处理 在查询方面的特点 nbsp nbsp nbsp 1 OLTP nbsp 单次查询返回数据量小 但是经常会涉及服务器端简单的聚合操作 要求查询响应速度快 一般应用于在线处理 nbsp nbsp nbsp 2 OLAP 单次查询返回数据量巨大 服务器端进行的处理复杂 经常包含上卷 从细粒度数据向高层的聚合 下钻 将汇总数据拆分到

    2026年1月23日
    0
  • 如何利用微信做营销?

    如何利用微信做营销?

    2021年8月28日
    50
  • 虚拟机怎么退出vi编辑模式_手机系统占用30个g正常吗

    虚拟机怎么退出vi编辑模式_手机系统占用30个g正常吗ESC键->冒号->小写q->(可选:不保存退出加个惊叹号!)->(可选:如文件需保存加个小写w)  当编辑完文件,准备退出Vi返回到shell时,可以使用以下几种方法之一。   (1)在命令模式中,连按两次大写字母Z,若当前编辑的文件曾被修改过,则Vi保存该文件后退出,返回到shell;若当前编辑的文件没被修改过,则Vi直接退出,返回到shel

    2022年9月30日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号