事务TransactionScope

System.Data.Common.DbTransaction

DbTransaction为单个事务

System.Transactions.TransactionScope

TransactionScope为分布式事务,同时启用MSDTC分布式事务

1)、如果代码中存在2个或者以上的数据库链接DbConnection,则需要启动微软的MSDTC分布式事务服务

2)、如果代码块中只有一个数据库DbConnection,那么实际上只有本地事务在处理,MSDTC分布式服务不用启用

3)、TransactionScope包含的代码块,本质是监控代码块里数据库链接DbConnection的个数

 

项目只有一个数据库,使用本地事务处理,如果每个实体类有自己的数据库链接,就会引发MSDTC;

所以共用一个DbConnection对象

如果有多个数据库,数据库使用相同的访问账号和密码,跨库处理只要加前缀(dbname..tablename),可以只使用本地事务处理就可以

-------------------------------

当某个方法单独执行的时候,它应该在一个单一的DbTransaction中执行;当多个方法一起执行的时候,它们应用共同在DbTransaction中执行

Transaction是一个抽象类,具有DbTransactionWrapper和Completed两个属性,前者表示对DbTransaction的封装,后者表示事务操作是否已经完成。

静态属性Current表示当前事务,这是一个基于当前线程的静态字段

 

TransactionScope

public class TransactionScope: IDisposable
    {
        private Transaction transaction = Transaction.Current;
        public bool Completed { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionStringName">连接字符串名称</param>
        /// <param name="isolationLevel">隔离级别</param>
        /// <param name="getFactory">用于创建DbProviderFactory的委托</param>
        public TransactionScope(string connectionStringName, IsolationLevel isolationLevel = IsolationLevel.Unspecified,
            Func<string, DbProviderFactory> getFactory = null)
        {
            if (null == transaction)//如果当前事务不存在
            {
                if (null == getFactory)
                {
                    getFactory = cnnstringName => DbHelper.GetFactory(cnnstringName);
                }
                DbProviderFactory factory = getFactory(connectionStringName);
                DbConnection connection = factory.CreateConnection();//根据DbProviderFactory创建DbConnection
                connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
                connection.Open();
                DbTransaction dbTransaction = connection.BeginTransaction(isolationLevel);//开启事务
                //开启的DbTransaction创建CommittableTransaction对象
                Transaction.Current = new CommittableTransaction(dbTransaction);
            }
            else
            {
                //服务过当前事务已经存在,直接调用DependentClone方法调用创建DependentTransaction作为当前事务
                Transaction.Current = transaction.DependentClone();
            }           
        }
        /// <summary>
        /// 事务完成后必须调用Complete方法提交事务
        /// </summary>
        public void Complete()
        {
            this.Completed = true;
        }
        public void Dispose()
        {
            Transaction current = Transaction.Current;
            Transaction.Current = transaction;
            if (!this.Completed)
            {
                current.Rollback();
            }
            CommittableTransaction committableTransaction = current as CommittableTransaction;
            if (null != committableTransaction)
            {
                if (this.Completed)
                {
                    committableTransaction.Commit();
                }
                committableTransaction.Dispose();
            }
        }
    }

DbTransactionWrapper

public class DbTransactionWrapper: IDisposable
    {
        /// <summary>
        /// 实例化DbTansaction
        /// </summary>
        /// <param name="transaction"></param>
        public DbTransactionWrapper(DbTransaction transaction)
        {
            this.DbTransaction = transaction;
        }
        public DbTransaction DbTransaction { get; private set; }//属性,表示对DbTransaction的封装
        public bool IsRollBack { get; set; }
        /// <summary>
        /// 回滚,直接调用同名方法
        /// </summary>
        public void Rollback()
        {
            if (!this.IsRollBack)
            {
                this.DbTransaction.Rollback();
            }
        }
        /// <summary>
        /// 提交,直接调用同名方法
        /// </summary>
        public void Commit()
        {
            this.DbTransaction.Commit();
        }
        /// <summary>
        /// 释放非托管资源,直接调用同名方法
        /// </summary>
        public void Dispose()
        {
            this.DbTransaction.Dispose();
        }
    }

    public abstract class Transaction : IDisposable
    {
        [ThreadStatic]
        private static Transaction current;//静态属性current表示当前事务,一个基于当前线程的静态字段,static在所有类的实例中共享

        public bool Completed { get; private set; }//属性,表示事务是否完成
        public DbTransactionWrapper DbTransactionWrapper { get; protected set; }
        protected Transaction() { }
        public void Rollback()
        {
            this.DbTransactionWrapper.Rollback();
        }
        public DependentTransaction DependentClone()
        {
            return new DependentTransaction(this);
        }
        public void Dispose()
        {
            this.DbTransactionWrapper.Dispose();
        }
        /// <summary>
        /// 
        /// </summary>
        public static Transaction Current
        {
            get { return current; }
            set { current = value; }
        }
    }
    /// <summary>
    /// 提交独立事务
    /// </summary>
    public class CommittableTransaction : Transaction
    {
        public CommittableTransaction(DbTransaction dbTransaction)
        {
            this.DbTransactionWrapper = new DbTransactionWrapper(dbTransaction);
        }
        public void Commit()
        {
            this.DbTransactionWrapper.Commit();
        }
    }
    /// <summary>
    /// 依附于某个事务的依赖事务
    /// </summary>
    public class DependentTransaction : Transaction
    {
        public Transaction InnerTransaction { get; private set; }
        /// <summary>
        /// 内部构造函数
        /// </summary>
        /// <param name="innerTransaction"></param>
        internal DependentTransaction(Transaction innerTransaction)
        {
            this.InnerTransaction = innerTransaction;
            this.DbTransactionWrapper = this.InnerTransaction.DbTransactionWrapper;
        }
    }

DbHelper

public class DbHelper
{
    public DbProviderFactory DbProviderFactory { get; private set; }
    public string ConnectionString { get; private set; }
    public static DbCommand[] AddCommands
    {
        get;
        set;
    }
    public virtual DbParameter BuildDbParameter(string name, object value)
    {
        DbParameter parameter = this.DbProviderFactory.CreateParameter();
        parameter.ParameterName = "@" + name;
        parameter.Value = value;
        return parameter;
    }
    public DbHelper()
    {
        var cnnStringSection = ConfigurationManager.ConnectionStrings["TestDb"];
        this.DbProviderFactory = DbProviderFactories.GetFactory(cnnStringSection.ProviderName);
        this.ConnectionString = cnnStringSection.ConnectionString;
    }
    public DbHelper(string cnnStringName)
    {
        var cnnStringSection = ConfigurationManager.ConnectionStrings[cnnStringName];
        this.DbProviderFactory = DbProviderFactories.GetFactory(cnnStringSection.ProviderName);
        this.ConnectionString = cnnStringSection.ConnectionString;
    }

    public static DbProviderFactory GetFactory(string cnnStringName)
    {
        var cnnStringSection = ConfigurationManager.ConnectionStrings[cnnStringName];
        return DbProviderFactories.GetFactory(cnnStringSection.ProviderName);
    }
    public void AdapterUpdate(string commandText,Func<DataTable, DataTable> updateTable)
    {
        DbConnection connection = null;
        using (connection = this.DbProviderFactory.CreateConnection())
        {
            try
            {
                DataTable dt = new DataTable();
                connection.ConnectionString = this.ConnectionString;
                DbCommand command = this.DbProviderFactory.CreateCommand();
                command.CommandText = commandText;
                command.Connection = connection;
                DbDataAdapter sda = this.DbProviderFactory.CreateDataAdapter();
                sda.SelectCommand = command;
                sda.Fill(dt);
                DbCommandBuilder scd = this.DbProviderFactory.CreateCommandBuilder();
                scd.DataAdapter=sda;
                DataTable changeTable = updateTable(dt.Copy()); 
                //changeTable.PrimaryKey = new DataColumn[] { changeTable.Columns[key] };
                sda.Update(changeTable.GetChanges());
                changeTable.AcceptChanges();
            }
            catch
            {
                throw;
            }
            finally
            {
                if (null == connection)
                {
                    connection.Dispose();
                }
            }
        }
    }
    public object GetSingle(string commandText)
    {
        return GetSingle(commandText,new DbParameter[0]);
    }
    public object GetSingle(string commandText, DbParameter[] parameter)
    {
        DbConnection connection = null;
        using (connection = this.DbProviderFactory.CreateConnection())
        {
            connection.ConnectionString = this.ConnectionString;
            DbCommand command = this.DbProviderFactory.CreateCommand();
            command.CommandText = commandText;
            command.Connection = connection;
            if (parameter.Length > 0) command.Parameters.AddRange(parameter);
            try
            {
                connection.Open();
                object obj = command.ExecuteScalar();
                if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value)))
                {
                    return null;
                }
                else
                {
                    return null;
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (null == connection)
                {
                    connection.Dispose();
                }
            }
        }
    }
    public int ExecuteCommand(string commmandText, DbParameter[] parameter, CommandType cmdType)
    {
        DbConnection connection = null;
        using (connection = this.DbProviderFactory.CreateConnection())
        {
            try
            {
                connection.ConnectionString = this.ConnectionString;
                DbCommand command = this.DbProviderFactory.CreateCommand();
                command.CommandText = commmandText;
                if(parameter.Length>0)command.Parameters.AddRange(parameter);
                command.CommandType = cmdType;
                command.Connection = connection;
                connection.Open();
                int result = command.ExecuteNonQuery();
                return result;
            }
            catch
            {
                throw;
            }
            finally
            {
                if (null == connection)
                {
                    connection.Dispose();
                }
            }
        }
    }
    public DataTable GetTable(string commandText)
    {
        return GetTable(commandText, new DbParameter[0], CommandType.Text);
    }
    public DataTable GetTable(string commandText, DbParameter[] parameter)
    {
        return GetTable(commandText, parameter, CommandType.Text);
    }
    public DataTable GetTable(string commandText, DbParameter[] parameter, CommandType cmdType)
    {
        DataTable dt = new DataTable();
        DbConnection connection=null;
        try
        {
            using (connection = this.DbProviderFactory.CreateConnection())
            {
                connection.ConnectionString = this.ConnectionString;
                DbCommand command = this.DbProviderFactory.CreateCommand();
                command.CommandText = commandText;
                command.CommandType = cmdType;
                command.Connection = connection;
                connection.Open();
                if (parameter.Length > 0) command.Parameters.AddRange(parameter);                
                DbDataAdapter dataAdapter = this.DbProviderFactory.CreateDataAdapter();
                dataAdapter.SelectCommand = command;
                dataAdapter.Fill(dt);
            }
        }
        catch
        {
            throw;
        }
        finally
        {
            if (null != connection)
            {
                connection.Dispose();
            }
        }
        return dt;
    }
    /// <summary>
    /// 执行sql
    /// </summary>
    /// <param name="commandText"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public int ExecuteNonQuery(string commandText, IDictionary<string, object> parameters)
    {
        DbConnection connection = null;
        DbCommand command = this.DbProviderFactory.CreateCommand();
        DbTransaction dbTransaction = null;
        try
        {
            command.CommandText = commandText;
            parameters = parameters ?? new Dictionary<string, object>();
            foreach (var item in parameters)
            {
                command.Parameters.Add(this.BuildDbParameter(item.Key, item.Value));
            }
            //如果当前事务存在,则将当前操作纳入封装的DbTransaction
            if (null != Artech.Transactions.Transaction.Current)
            {
                command.Connection = Artech.Transactions.Transaction.Current.DbTransactionWrapper.DbTransaction.Connection;
                command.Transaction = Artech.Transactions.Transaction.Current.DbTransactionWrapper.DbTransaction;
            }
            else
            {
                //如果System.Transactions.Transaction.Current属性返回的事务存在,操作的执行自动纳入该事务中
                connection = this.DbProviderFactory.CreateConnection();
                connection.ConnectionString = this.ConnectionString;
                command.Connection = connection;
                connection.Open();
                //
                if (System.Transactions.Transaction.Current == null)
                {//如果两种事务均不存在,则创建一个单独的DbTransaction并将相应的操作纳入其中
                    dbTransaction = connection.BeginTransaction();
                    command.Transaction = dbTransaction;
                }
            }
            int result = command.ExecuteNonQuery();
            if (null != dbTransaction)
            {
                dbTransaction.Commit();
            }
            return result;
        }
        catch
        {
            if (null != dbTransaction)
            {
                dbTransaction.Rollback();
            }
            throw;
        }
        finally
        {
            if (null != connection)
            {
                connection.Dispose();
            }
            if (null != dbTransaction)
            {
                dbTransaction.Dispose();
            }
            command.Dispose();
        }
    }
}

 

posted @ 2016-08-09 13:21  wjl910  阅读(161)  评论(0)    收藏  举报