zoukankan      html  css  js  c++  java
  • 咱也搞一个TransactionScope

    先来上一段MSDN里TransactionScope的介绍

    TransactionScope 类提供一个简单方法,通过这一方法,您不必与事务本身交互,即可将代码块标记为参与某个事务。事务范围可以自动选择和管理环境事务。由于它易于使用并且效率很高,因此建议您在开发事务应用程序时使用 TransactionScope 类。

    此外,您不必显式向事务登记资源。任何 System.Transactions 资源管理器(例如 SQL Server 2005)都可以检测到该范围创建的环境事务的存在并自动登记。


    更详细一点的,可以看下面这个网页
    http://idior.cnblogs.com/archive/2005/08/15/214300.html


    为什么不用自带的"TransactionScope

    先简单说说(因为我主要想说他和缺点)TransactionScope的优点:
    一:使用起来比较方便.TransactionScope可以实现隐式的事务,使你可以在写数据访问层代码的时候不用

    考虑到事务,而在业务层的控制事务.关于这点,可以看Petshop4.0.
    二:可以实现分布式事务,比如跨库或MSMQ. 关于这个偶就不用多说了,哈哈.地球人都知道!
    好了,说完了好处,来,开始批斗了....蹲地上,唱东方红....


    缺点

    一:性价比不高.比如,你只是在"Scope"里控制一个库的事务.用"TransactionScope"就有点TMD(请原谅我这

    么激动,实现是太不值得了)的浪费了.
    二:一般情况下只要你使用"TransactionScope",都要配置MSDTC,要配防火墙,要开139(记不清了,貌似是这个

    )端口.问过专业大牛,人家说了,这个端口不可以更改,日(对不起,我太生气了..)

    基于上面这二个问题,偶们决定"Scope"再好,偶们也不用了(拼了),但是,偶们还想实现那种类似于隐式的

    事务代码(这个太勾引人了).于是,偶们搞出了这个自己的"Scope"(注意,偶这个只能实现数据库的事务而且不是分布式的,当然不用开端口,也基本无性能问题).

    实现原理
     偶是不指望实现自己的事务管理器来实现自己"Scope"了,于是偶想到了这个办法分三步实现.
    一.在实例化自己的"Scope"时,记一个事务标志位.
    二.在访问数据库时,查看有没有事务标志位.如果有,从"Scope"取一个数据库事务.将这个事务赋给DBCommand,并将这个事务和连接记下来,如果下次有同样的连接字符串请示事务,就将这个事务发给他.
    三.在我们的"Scope"被Dispose时,判断用户调没调用Complete方法,如果调了,说明用户提交了事务,没调就说明事务回滚(和"TransactionScope"是一样的).然后提交或回滚所有的DBTransaction.

    根据上面的实现,偶们需要控制用户数据访问方式,也就是说让他们用偶们提供的数据访问代码,才能实现我们自己的"Scope".于是,偶想到了企业库.偶用的是企业库3.1版的

    下面开始放代码
    先放实现后的调用代码,是不是和"TransactionScope"很像?
    DJTransactionScope (偶这个项目是DJ开头的,DJ呵呵)

    using(DJTransactionscope scope=new (DJTransactionscope ())

    {

    //要确保对支持事务的资源的登记放在此范围内,如数据库资源的打开

    A a
    =new A();

    a.method();

    ..
    B b 
    = new b();
    b.method();

    scope.comlete()

    }
     



    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    using System.Data.Common;
    using Microsoft.Practices.EnterpriseLibrary.Data;
    using System.Web;
    using System.Threading;

    namespace DJ.Framework.Transaction
    {
        
    public class DJTransactionScope : IDisposable
        
    {
            
    /// <summary>
            
    /// 标志位,标志用户是不是提交了事务
            
    /// </summary>

            private bool isCompleted = false;
            
    /// <summary>
            
    /// 存放已加入的事务的Connection的
            
    /// </summary>

            private Dictionary<String, ConnAndTranPaire> transactionPool = new Dictionary<string, ConnAndTranPaire>();

            
    /// <summary>
            
    /// 用来存放WinFrom程序中的事务
            
    /// </summary>

            [ThreadStatic]
            
    private static DJTransactionScope currentScope;

            
    /// <summary>
            
    /// 取得当前事务
            
    /// </summary>

            public static DJTransactionScope Current
            
    {
                
    get
                
    {
                    
    //如果这不是一个Web项目
                    if (HttpContext.Current == null)
                    
    {
                        
    return currentScope;
                    }

                    
    else
                    
    {
                        
    //Web项目的话,就把事务标志放到HttpContext中
                        HttpContext context = HttpContext.Current;
                        
                        
    return context.Items["CurrentTransactionScope"as DJTransactionScope;
                    }

                }

                
    private set
                
    {
                    
                    
    if (HttpContext.Current == null)
                    
    {
                        currentScope 
    = value;
                    }

                    
    else
                    
    {
                        HttpContext context 
    = HttpContext.Current;
                      

                        
    if (context.Items.Contains("CurrentTransactionScope"))
                            context.Items[
    "CurrentTransactionScope"= value;
                        
    else
                            context.Items.Add(
    "CurrentTransactionScope", value);
                       
                    }

                }

            }


            
    private Guid scopeID = Guid.NewGuid();
            
    /// <summary>
            
    /// 事务ID
            
    /// </summary>

            public Guid ScopeID
            
    {
                
    get
                
    {
                    
    return scopeID;
                }

            }


            
    /// <summary>
            
    /// 构造方法
            
    /// </summary>

            public DJTransactionScope()
            
    {
                
    //如果当前没有起动事务,就记下此标志
                if (Current == null)
                
    {
                    Current 
    = this;
                }

            }


            
    /// <summary>
            
    /// 调用此方法,将会在代码段结束后提交事务
            
    /// </summary>

            public void Complete()
            
    {
                
    //记录用户的提示
                isCompleted = true;
            }


            
    /// <summary>
            
    /// 加入当前事务
            
    /// </summary>
            
    /// <param name="database"></param>
            
    /// <returns></returns>

            public DbTransaction JoinTransaction(Database database)
            
    {
                
                
    if (transactionPool.ContainsKey(database.ConnectionStringWithoutCredentials))
                
    {
                    
    return transactionPool[database.ConnectionStringWithoutCredentials].Transaction;
                }

                
    else
                
    {

                    DbConnection dbconnection 
    = database.CreateConnection();
                    dbconnection.Open();
                    DbTransaction dbTransaction 
    = dbconnection.BeginTransaction();

                    ConnAndTranPaire paire 
    = new ConnAndTranPaire();

                    paire.Connection 
    = dbconnection;
                    paire.Transaction 
    = dbTransaction;

                    transactionPool.Add(database.ConnectionStringWithoutCredentials, paire);
                    
    return paire.Transaction;

                }

            }


            
    public override bool Equals(object obj)
            
    {
                
    if (obj is DJTransactionScope)
                
    {
                    DJTransactionScope scope 
    = obj as DJTransactionScope;

                    
    return (scope.scopeID == this.scopeID);
                }


                
    return false;

            }


            
    public override int GetHashCode()
            
    {
                
    return scopeID.GetHashCode();
            }


            
    IDisposable 成员

            
    private void RemoveTransaction()
            
    {
                Current 
    = null;
            }

        }


        
    /// <summary>
        
    /// 放事务和连接类
        
    /// </summary>

        class ConnAndTranPaire
        
    {
            
    public DbConnection Connection;
            
    public DbTransaction Transaction;
        }

    }


    偶建议把上面这个类放到一个单独的DLL里

    下的代码包装了企业的数据访问部分

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Data.Common;
    using System.Reflection;
    using Microsoft.Practices.EnterpriseLibrary.Data;
    using Microsoft.Practices.EnterpriseLibrary.Data.Sql;
    using Microsoft.Practices.EnterpriseLibrary.Data.Oracle;
    using DJ.Framework.DataObjects;
    using DJ.Framework.Transaction;

    namespace DJ.Framework.DataAccess
    {
        
    public class ExDatabase
        
    {
            
    protected Database innerDatabase;

            
    protected ExDatabase(Database database)
            
    {
                innerDatabase 
    = database;
            }


            
    /// <summary>
            
    /// 获取ExDatabase实例
            
    /// </summary>
            
    /// <returns>ExDatabase实例</returns>

            public static ExDatabase CreateDatabase()
            
    {
                
    return new ExDatabase(DatabaseFactory.CreateDatabase());
            }


            
    /// <summary>
            
    /// 获取ExDatabase实例
            
    /// </summary>
            
    /// <param name="name">连接标识</param>
            
    /// <returns>ExDatabase实例</returns>

            public static ExDatabase CreateDatabase(String name)
            
    {
                
    return new ExDatabase(DatabaseFactory.CreateDatabase(name));
            }


           

            
    Execute Something

            
    Update DataSet

            
    Load DataSet

            
    Parameter Function

            
    Get Something
        }

    }

    好的,到这里,我们自己的"Scope"就实现了.
    优点就是不用起分布式事务,隐式的实现事务(至少看起来是)
    缺点,就是不支持真正的分布式事务.只能起数据库事务,必须用我们封装的数据访问代码


    先放到这,有没写的明白的地方,请大家留言给我,我会补充上来



  • 相关阅读:
    python socket 二进制
    全面介绍内存管理机制
    glog修改
    mysql c api
    http twisted
    IOCP 模型1
    IOCP 模型2 AcceptEx
    python
    Python Twisted
    Java 拾遗
  • 原文地址:https://www.cnblogs.com/listhome/p/979603.html
Copyright © 2011-2022 走看看