事务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(); } } }

浙公网安备 33010602011771号