zoukankan      html  css  js  c++  java
  • 事务之美

    在数据库编程中,事务是经常需要用到的技术,在.net平台上,事务处理是非常好用的,但是本人还是认为有专门的数据库服务器的话还是把事物放在存储过程里更显更科学一点。

    其实添加数据是引起数据库并发操作的一个常见显示,事务完全可以屏蔽这一点

        Declare @id int
        BEGIN TRANSACTION
      
           Insert into xxxxxTable(f1,f2)values(@a,@b)
           Select @id=@@identity
            Insert into abcTable(ff1,ff2,ff3)values(@c,@id,@dd)      

            IF @@error <> 0  --发生错误
            BEGIN
                ROLLBACK TRANSACTION
                RETURN 0
            END
            ELSE
            BEGIN
                COMMIT TRANSACTION
                RETURN 1    --执行成功
           END

     以下是各种事务总结

    在一个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 RegionDescription=@UpdateValue 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:

    /// <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 ID=sa;Password=123;");
                SqlCommand cmd 
    = new SqlCommand();
                
    try
                
    {
                    cmd.CommandText 
    = "Update Region Set RegionDescription=@UpdateValue 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:

     /// <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 ID=sa;Password=123;");
                 SqlCommand cmd 
    = new SqlCommand();
                
    try
                
    {
                  
                    
    using (System.Transactions.TransactionScope ts = new TransactionScope())
                    
    {
                        
                        cmd.CommandText 
    = "Update Region Set RegionDescription=@UpdateValue 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();
                    }

                }

                
    catch
                
    {
                    
    throw;
                }

                
    finally
                
    {
                    conn.Close();
                }


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

    在.net中还有些也能进行事务处理,如web Service中

    需要特别补充的是:
    如果你使用的是分布事务(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命令就可以了

  • 相关阅读:
    为什么有时候程序出问题会打印出“烫烫烫烫...
    VC++共享数据段实现进程之间共享数据
    IEEE浮点数float、double的存储结构
    前端智勇大闯关
    Python:高级主题之(属性取值和赋值过程、属性描述符、装饰器)
    来认识下less css
    Koala Framework
    在使用Kettle的集群排序中 Carte的设定——(基于Windows)
    标准库类型
    iOS多线程的初步研究1
  • 原文地址:https://www.cnblogs.com/dfsxh/p/1365999.html
Copyright © 2011-2022 走看看