【转载】.Net中的种事务总结

本文介绍了在MIS系统中使用的四种事务处理方法,包括SQL事务、ADO.net事务、TransactionScope事务和COM+事务,并详细阐述了各自的优缺点及应用场景。
在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了。因此掌握事务处理的方法是很重要,进我的归类在.net中大致有以下4种事务处理的方法。大家可以参考一下,根据实际选择适当的事务处理。
1、SQL事务
    sql事务是使用SQL server自身的事务:在存储过程中直接使用Begin Tran,Rollback Tran,Commit Tran实现事务:
优点:执行效率最佳
限制:事务上下文仅在数据库中调用,难以实现复杂的业务逻辑。
Demo:(所有demo,都以SQL Server自带的Northwind数据的表Region为例)

带事务的存储过程

CREATE PROCEDURE dbo.SPTransaction
(
    @UpdateID int,
    @UpdateValue nchar(50),
    @InsertID int,
    @InsertValue nchar(50)
)
AS
begin Tran
  Update Region  Set where RegionID=@UpdateID

  insert into Region Values (@InsertID,@InsertValue)

  declare @RegionError int
  select @RegionError=@@error
  if(@RegionError=0)
   COMMIT Tran
  else
   ROLLBACK Tran
  GO

 

2、ADO.net事务
      Ado.net事务可能是大家一般都用的
     优点:简单,效率和数据库事务差不多。
     缺点:事务不能跨数据库,只能在一个数据库连接上。如果是两个数据库上就不能使用该事务了。
    Demo:

   ADO.net事务
       

/**//// <summary>
        /// 一般的ADO.net 事务
        /// </summary>
        public void ADONetTran1()
        {
            SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );
            SqlCommand cmd = new SqlCommand();
            try
            {
                cmd.CommandText = "Update Region Set where RegionID=@UpdateID";
                cmd.CommandType = CommandType.Text;
                cmd.Connection = conn;
                conn.Open();
                SqlParameter[] paras = new SqlParameter[]{
                                        new SqlParameter ("@UpdateID",SqlDbType.Int,32),
                                        new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
                paras[0].Value = "2";
                paras[1].Value = "Update Value12";

                foreach (SqlParameter para in paras)
                {
                    cmd.Parameters.Add(para);
                }
                //开始事务
                cmd.Transaction = conn.BeginTransaction();
                cmd.ExecuteNonQuery();


                cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
                cmd.CommandType = CommandType.Text;

                paras = new SqlParameter[]{
                                        new SqlParameter ("@InsertID",SqlDbType.Int ,32),
                                        new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
                paras[0].Value = "7";
                paras[1].Value = "Insert Value";

                cmd.Parameters.Clear();
                foreach (SqlParameter para in paras)
                {
                    cmd.Parameters.Add(para);
                }
                
                cmd.ExecuteNonQuery();
                //提交事务
                cmd.Transaction.Commit();
            }
            catch
            {
                //回滚事务
                cmd.Transaction.Rollback();
                throw;
            }
            finally
            {
                conn.Close();
            }

        }



3、TransactionScope事务
       TransactionScope事务类,它可以使代码块成为事务性代码。并自动提升为分布式事务
       优点:实现简单,同时能够自动提升为分布式事务
       Demo:

       TransactionScope事务
       

 /**//// <summary>
        /// TransactionScope事务:可自动提升事务为完全分布式事务的轻型(本地)事务。 
        /// 使用时要保证MSDTC服务(控制分布事务)是开启的可以使用:net start msdtc命令开启服务;
        /// </summary>
        public void ADONetTran2()
        {
             SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );
             SqlCommand cmd = new SqlCommand();
            try
            {
              
                using (System.Transactions.TransactionScope ts = new TransactionScope())
                {
                    
                    cmd.CommandText = "Update Region Set where RegionID=@UpdateID";
                    cmd.CommandType = CommandType.Text;
                    cmd.Connection = conn;
                    conn.Open();
                    SqlParameter[] paras = new SqlParameter[]{
                                        new SqlParameter ("@UpdateID",SqlDbType.Int,32),
                                        new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
                    paras[0].Value = "2";
                    paras[1].Value = "Update Value12";

                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }
                    cmd.ExecuteNonQuery();


                    cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
                    cmd.CommandType = CommandType.Text;

                    paras = new SqlParameter[]{
                                        new SqlParameter ("@InsertID",SqlDbType.Int ,32),
                                        new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
                    paras[0].Value = "8";
                    paras[1].Value = "Insert Value";

                    cmd.Parameters.Clear();
                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }

                    cmd.ExecuteNonQuery();
                    //提交事务
                    ts.Complete();              //提交事务之前conn不能关闭的(Not conn.Close()),否则报错
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                conn.Close();
            }

        }



4、COM+事务
      在分布式应用程序中,往往要同时操作多个数据库,使用数据库事务就不能满足业务的要求了。在COM+中,提供完整的事务处理服务。很方便处理多个数据库上的事务。


     例一:

     COM+事务
      

  /**//// <summary>
        /// COM+事务
        /// </summary>
        public void ComTran()
        {
            SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );
            SqlCommand cmd = new SqlCommand();
            ServiceConfig sc = new ServiceConfig();

            //指定事务类型
            sc.Transaction = TransactionOption.Required;
            //设置启动跟踪
            sc.TrackingEnabled = true;
            //创建一个上下文,该上下文的配置由作为 cfg 参数传递的 ServiceConfig 对象来指定。
            //随后,客户端和服务器端的策略均被触发,如同发生了一个方法调用。
            //接着,新的上下文被推至上下文堆栈,成为当前上下文
            ServiceDomain.Enter(sc);
            try
            {
                    cmd.CommandText = "Update Region Set where RegionID=@UpdateID";
                    cmd.CommandType = CommandType.Text;
                    cmd.Connection = conn;
                    conn.Open();
                    SqlParameter[] paras = new SqlParameter[]{
                                        new SqlParameter ("@UpdateID",SqlDbType.Int,32),
                                        new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
                    paras[0].Value = "2";
                    paras[1].Value = "Update Value22";

                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }
                    cmd.ExecuteNonQuery();


                    cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
                    cmd.CommandType = CommandType.Text;

                    paras = new SqlParameter[]{
                                        new SqlParameter ("@InsertID",SqlDbType.Int ,32),
                                        new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
                    paras[0].Value = "9";
                    paras[1].Value = "Insert Value";

                    cmd.Parameters.Clear();
                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }

                    cmd.ExecuteNonQuery();

                    //提交事务
                    ContextUtil.SetComplete();
            }
            catch
            {
                //回滚事务
                ContextUtil.SetAbort();
                throw;
            }
            finally
            {
                conn.Close();
                //触发服务器端的策略,随后触发客户端的策略,如同一个方法调用正在返回。
                //然后,当前上下文被弹出上下文堆栈,调用 Enter 时正在运行的上下文成为当前的上下文。
                ServiceDomain.Leave();
            }

 

需要特别补充的是:
如果你使用的是分布事务(TransactionScope事务和COM+事务),在默认情况下你是要重新配置安装SQL Server数据库服务器和访问数据库的客户端的.(如果没有配置运行会出现以下错误:该伙伴事务管理器已经禁止了它对远程/网络事务的支持。 (异常来自 HRESULT:0x8004D025))

下面是MSDN上关于配置分布式事务的一段原话:
配置分布式事务
要启用分布式事务,可能需要通过网络启用 MS DTC,以便在使用应用了最新的 Service Pack 的较新操作系统(例如 Windows XP 或 Windows 2003)时使用分布式事务。如果启用了 Windows 防火墙(Windows XP Service Pack 2 的默认设置),必须允许 MS DTC 服务使用网络或打开 MS DTC 端口。
实际怎么配置呢,经过我的实际使用:大致如下:打开'控制面板'->'管理工具'->'组件服务',点开'组件服务'->'计算机'->'我的电脑',在'我的电脑'上右击属性,点'MSDTC',然后点'安全性配置'。作为数据库的服务器的配置如下:


而访问数据库的客户端的配置和服务器端的稍有些差别:


在设置完上面的还有使防火墙MS DTC 服务使用网络或打开 MS DTC 端口:运行netsh firewall set allowedprogram %windir%\system32\msdtc.exe MSDTC enable命令就可以了

ASP.NET事务可以说是在.NET平台上事务实现方式最简单的一种,你仅仅需要一行代码即可。在aspx的页面声明中加一个额外的属性,即事务属性Transaction="Required",它有如下的值:Disabled(默认)、NotSupported、Supported、Required和RequiresNew,这些设置和COM+及企业级服务中的设置一样,典型的一个例子是如果你想在页面上下文中运行事务,那么要将其设置为Required。如果页面中包含有用户控件,那么这些控件也会包含到事务中,事务会存在于页面的每个地方。

页面声明Transaction="Required":

<%@ Page Transaction="Required"  Language="C#" AutoEventWireup="true"

CodeBehind="WebForm3.aspx.cs" Inherits="WebApplication4.WebForm3" %>

页面引用:using System.EnterpriseServices;。

然后,数据操作代码:

protected void Button1_Click(object sender, EventArgs e)

{

    try

    {

        Work1();

        Work2();

        ContextUtil.SetComplete();   //提交事务

    }

    catch (System.Exception except)

        ContextUtil.SetAbort();      //撤销事务

        Response.Write(except.Message);

    } 

} 

private void Work1()

{

    string conString = "data source=127.0.0.1;database=codematic;user >

      password=";

    SqlConnection myConnection = new SqlConnection(conString);

    string strSql = "Insert Into P_Category(CategoryId,Name)values('1',

      'test1')";

    SqlCommand myCommand = new SqlCommand(strSql, myConnection);

    myConnection.Open();

    int rows = myCommand.ExecuteNonQuery();

    myConnection.Close();

}

private void Work2()

{

    string conString = "data source=127.0.0.1;database=codematic;user >

      password=";

    SqlConnection myConnection = new SqlConnection(conString);

    string strSql = "Insert Into P_Category(CategoryId,Name)values('2',

      'test2')";

    SqlCommand myCommand = new SqlCommand(strSql, myConnection);

    myConnection.Open();

    int rows = myCommand.ExecuteNonQuery();

    myConnection.Close();

}

 

ContextUtil是用于获取 COM+ 上下文信息的首选类。由于此类的成员全部为static,因此在使用其成员之前不需要对此类进行实例化。

ASP.NET页面事务的优势和限制如下。

    l限制:页面的所有代码都是同一个事务,这样的事务可能会很大,而也许我们需要的是分开的、小的事务实现在Web层。

 

原载地址: http://www.cnblogs.com/hanjiheng/archive/2011/06/01/2067505.html
4.3 事务的传播机制 REQUIRED (默认) 支持当前事务,如果当前没有事务,则新建事务 如果当前存在事务,则加入当前事务,合并成一个事务 REQUIRES_NEW 新建事务,如果当前存在事务,则把当前事务挂起(无论当前环境是否有事物) 这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交 NESTED 如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交 如果当前没有事务,则新建事务 如果它异常,父级可以捕获它的异常而不进行回滚,正常提交 但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别 SUPPORTS 如果当前存在事务,则加入事务 如果当前不存在事务,则以非事务方式运行,这个和不写没区别 NOT_SUPPORTED 以非事务方式运行 如果当前存在事务,则把当前事务挂起 MANDATORY 如果当前存在事务,则运行在当前事务中 如果当前无事务,则抛出异常,也即父级方法必须有事务 NEVER 以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务 一般用得比较多的是 REQUIRED, REQUIRES_NEW; REQUIRES_NEW 一般用在子方法需要单独事务。 @Transactional(propagation = Propagation.REQUIRED) 4.4 事务的失效场景 ———————————————— 版权声明:本文为优快云博主「Gao_xu_sheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Gao_xu_sheng/article/details/136727470
最新发布
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值