public async Task Execute(DTOperationRecord record, Func <Task> action) { try { await using (DBTransactionScope scope = new DBTransactionScope(System.Transactions.TransactionScopeOption.Required, new System.Transactions.TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 0, 10) })) { await _dtOperationRecordStore.UpdateVersion(record.StoreGroupName, record.HashInfo, record.ID, Guid.NewGuid().ToString()); await action(); await _dtOperationRecordStore.UpdateStatus(record.StoreGroupName, record.HashInfo, record.ID, (int)DTOperationRecordStatus.Complete); scope.Complete(); } } catch { var nRecord = await _dtOperationRecordStore.QueryByID(record.StoreGroupName, record.HashInfo, record.ID); if (nRecord != null) { await nRecord.Cancel(); } throw; } }
public async Task Cancel(DTOperationData data) { if (data.Status == (int)DTOperationDataStatus.Cancel) { return; } var service = getService(data.Type); await using (DBTransactionScope transactionScope = new DBTransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 30, 0) })) { await service.Cancel(data.Data); var updateResult = await _dtOperationDataStore.UpdateStatus(data.StoreGroupName, data.HashInfo, data.ID, data.Version, (int)DTOperationDataStatus.Cancel); if (!updateResult) { var fragment = new TextFragment() { Code = TextCodes.DTOperationDataConcurrenceErrorInCancel, DefaultFormatting = "分布式操作数据在Cancel时发生并发错误,StoreGroupName:{0},HashInfo:{1}", ReplaceParameters = new List <object>() { data.StoreGroupName, data.HashInfo, data.ID.ToString() } }; throw new UtilityException((int)Errors.DTOperationDataConcurrenceErrorInCancel, fragment); } transactionScope.Complete(); } }
public DBTransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, Action rollbackAction = null) { _preTransactionScope = _transactionScope.Value; _transactionScope.Value = this; _rollbackAction = rollbackAction; _preConnections = _connections.Value; _preTransactionInfo = _transactionInfo.Value; _transactionInfo.Value = new TransactionInfo() { ID = Guid.NewGuid(), ScopeOption = scopeOption, TransactionOptions = transactionOptions }; _id = _transactionInfo.Value.ID; _scopeOption = _transactionInfo.Value.ScopeOption; _transactionOptions = _transactionInfo.Value.TransactionOptions; if (_preTransactionInfo == null) { _needCreateNewTransaction = true; } else { if (_preTransactionInfo.TransactionOptions.IsolationLevel != transactionOptions.IsolationLevel) { _needCreateNewTransaction = true; } else { _needCreateNewTransaction = false; } } if (!_inTransaction.Value) { _needClearTransactionScope = true; } _inTransaction.Value = true; //如果是范围是新事务或者忽略,则_needClose=true if (scopeOption == TransactionScopeOption.RequiresNew || scopeOption == TransactionScopeOption.Suppress) { _needClose = true; _connections.Value = new Dictionary <string, DBConnectionContainer>(); if (scopeOption == TransactionScopeOption.Suppress) { _inTransaction.Value = false; } } else if (scopeOption == TransactionScopeOption.Required && _preConnections == null) { //如果是Required,并且_preConnections为空,则_needClose=true _connections.Value = new Dictionary <string, DBConnectionContainer>(); _needClose = true; } else { if (_connections.Value == null) { _connections.Value = new Dictionary <string, DBConnectionContainer>(); } _needClose = false; } }
/// <summary> /// SQL事务处理封装 /// </summary> /// <param name="isOnlyRead">是否是只读</param> /// <param name="isInnerTranaction">当不在事务环境中时,是否需要开启事务</param> /// <param name="strConn">连接字符串</param> /// <param name="callBack">处理回调函数</param> public static async Task SqlTransactionWorkAsync(string dbType, bool isOnlyRead, bool isInnerTranaction, string strConn, Func <DbConnection, DbTransaction, Task> callBack, System.Transactions.IsolationLevel innerTransactionIsolationLevel = System.Transactions.IsolationLevel.ReadCommitted) { if (!_dbConnGenerates.TryGetValue(dbType, out IDBConnGenerate dbConnGenerate)) { throw new Exception($"not found {dbType} in DBTransactionHelper.DBConnGenerates"); } DbConnection conn = null; DbTransaction transaction = null; //如果当前处于事务环境中 if (DBTransactionScope.InScope()) { //检查是否已经在事务中创建过连接 if (DBTransactionScope.CurrentConnections.ContainsKey(strConn.ToLower()) && (DBTransactionScope.CurrentConnections[strConn.ToLower()].Connection.State == ConnectionState.Connecting || DBTransactionScope.CurrentConnections[strConn.ToLower()].Connection.State == ConnectionState.Open)) { conn = DBTransactionScope.CurrentConnections[strConn.ToLower()].Connection; transaction = await DBTransactionScope.CurrentConnections[strConn.ToLower()].CreateTransactionAsync(async(connection, options) => { return(await CreateTransactionAsync(dbConnGenerate, connection, options)); }); await callBack(conn, transaction); } else { //只读连接在事务中的时候需要做隔离,防止提升到分布式事务 if (isOnlyRead) { //using (var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled)) //{ await using (conn = dbConnGenerate.Generate(strConn)) { await conn.OpenAsync(); //判断IsolationLevel是否是ReadUncommitted,如果是,则需要单独创建事务 if (DBTransactionScope.CurrentTransactionInfo.TransactionOptions.IsolationLevel == System.Transactions.IsolationLevel.ReadUncommitted) { transaction = await dbConnGenerate.GenerateTransactionAsync(conn, ConvertIsolationLevel(DBTransactionScope.CurrentTransactionInfo.TransactionOptions.IsolationLevel)); } else { transaction = null; } await callBack(conn, transaction); if (transaction != null) { await transaction.CommitAsync(); } await conn.CloseAsync(); } // transactionScope.Complete(); //} } else { //如果是写连接,需要加入到事务连接列表中 conn = dbConnGenerate.Generate(strConn); await conn.OpenAsync(); DBTransactionScope.CurrentConnections[strConn.ToLower()] = new DBTransactionScope.DBConnectionContainer() { Connection = conn, Error = true }; transaction = await DBTransactionScope.CurrentConnections[strConn.ToLower()].CreateTransactionAsync(async(connection, options) => { return(await CreateTransactionAsync(dbConnGenerate, connection, options)); }); await callBack(conn, transaction); } } } else { //不在事务中,需要创建连接,由isInnerTranaction确定是否需要创建事务 if (isInnerTranaction) { //using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled)) //{ await using (conn = dbConnGenerate.Generate(strConn)) { await conn.OpenAsync(); transaction = await dbConnGenerate.GenerateTransactionAsync(conn, ConvertIsolationLevel(innerTransactionIsolationLevel)); await callBack(conn, transaction); await transaction.CommitAsync(); await conn.CloseAsync(); } // transactionScope.Complete(); //} } else { await using (conn = dbConnGenerate.Generate(strConn)) { await conn.OpenAsync(); await callBack(conn, null); await conn.CloseAsync(); } } } }