/// <summary> /// Adds a row lock to the list of locks that must be released at the end of a transaction. /// </summary> /// <param name="enlistment">Facilitates communication bewtween an enlisted transaction participant and the transaction /// manager during the final phase of the transaction.</param> public void InDoubt(global::System.Transactions.Enlistment enlistment) { /*This method is called for volatile resources when the transaction manager has invoked a single phase commit * operation to a single durable resource, * and then connection to the durable resource was lost prior to getting the transaction result. * At that point, the transaction outcome cannot be safely determined. * As InDoubt is considered to be a final state for a transaction, you should not call Commit or Rollback after calling InDoubt. */ try { global::FluidTrade.Core.EventLog.Information("<<<***>>> DataModelTransaction InDoubt"); } catch { } if (this.ClearRowLockList()) { try { global::FluidTrade.Core.EventLog.Information("<<<***>>> DataModelTransaction InDoubt cleared rows in List"); } catch { } } }
/// <summary> /// Adds a row lock to the list of locks that must be released at the end of a transaction. /// </summary> /// <param name="enlistment">Facilitates communication bewtween an enlisted transaction participant and the transaction /// manager during the final phase of the transaction.</param> public void Rollback(global::System.Transactions.Enlistment enlistment) { this.recordList.Reverse(); try { DataModel.DataLock.EnterWriteLock(); for (int recordIndex = 0; (recordIndex < this.recordList.Count); recordIndex = (recordIndex + 1)) { global::FluidTrade.Core.IRow iRow = this.recordList[recordIndex]; if (((iRow.RowState == global::System.Data.DataRowState.Added) || ((iRow.RowState == global::System.Data.DataRowState.Deleted) || (iRow.RowState == global::System.Data.DataRowState.Modified)))) { iRow.RejectChanges(); } } } finally { this.ClearRowLockList(); DataModel.DataLock.ExitWriteLock(); try { //txn is done remove this txn from the threads stack //in theory the stack should only be accessed from the same thread so dont need a lock //although might want to look at the stack through the DataModelTransaction //via another thread. so lock just to be safe lock (this.dataModelTransactionStack) this.dataModelTransactionStack.Pop(); } catch (Exception ex) { try { global::FluidTrade.Core.EventLog.Information("Error in Commit dataModelTransactionStack.Pop {0}\r\n{1}", ex.Message, ex.StackTrace); } catch { } } } enlistment.Done(); }
/// <summary> /// Adds a row lock to the list of locks that must be released at the end of a transaction. /// </summary> /// <param name="enlistment">Facilitates communication bewtween an enlisted transaction participant and the transaction /// manager during the final phase of the transaction.</param> public void Commit(global::System.Transactions.Enlistment enlistment) { try { global::System.Collections.Generic.List <object> transactionLogItem = new global::System.Collections.Generic.List <object>(); DataModel.TransactionLogLock.EnterWriteLock(); DataModel.DataLock.EnterWriteLock(); for (int recordIndex = 0; (recordIndex < this.recordList.Count); recordIndex = (recordIndex + 1)) { global::FluidTrade.Core.IRow iRow = this.recordList[recordIndex]; global::FluidTrade.Core.ITable iTable = ((global::FluidTrade.Core.ITable)(iRow.Table)); if ((iRow.RowState == global::System.Data.DataRowState.Modified)) { transactionLogItem.Clear(); transactionLogItem.Add(global::FluidTrade.Core.RecordState.Modified); transactionLogItem.Add(iTable.Ordinal); for (int keyIndex = 0; (keyIndex < iTable.PrimaryKey.Length); keyIndex = (keyIndex + 1)) { transactionLogItem.Add(iRow[iTable.PrimaryKey[keyIndex]]); } for (int columnIndex = 0; (columnIndex < iTable.Columns.Count); columnIndex = (columnIndex + 1)) { if ((iRow[columnIndex].Equals(iRow[columnIndex, global::System.Data.DataRowVersion.Original]) == false)) { transactionLogItem.Add(columnIndex); transactionLogItem.Add(iRow[columnIndex]); } } DataModel.AddTransaction(iRow, transactionLogItem.ToArray()); iRow.AcceptChanges(); } else { if ((iRow.RowState == global::System.Data.DataRowState.Added)) { transactionLogItem.Clear(); transactionLogItem.Add(global::FluidTrade.Core.RecordState.Added); transactionLogItem.Add(iTable.Ordinal); for (int keyIndex = 0; (keyIndex < iTable.PrimaryKey.Length); keyIndex = (keyIndex + 1)) { transactionLogItem.Add(iRow[iTable.PrimaryKey[keyIndex]]); } for (int columnIndex = 0; (columnIndex < iTable.Columns.Count); columnIndex = (columnIndex + 1)) { if ((iRow[columnIndex].Equals(iTable.Columns[columnIndex].DefaultValue) == false)) { transactionLogItem.Add(columnIndex); transactionLogItem.Add(iRow[columnIndex]); } } DataModel.AddTransaction(iRow, transactionLogItem.ToArray()); iRow.AcceptChanges(); } else { transactionLogItem.Clear(); transactionLogItem.Add(global::FluidTrade.Core.RecordState.Deleted); transactionLogItem.Add(iTable.Ordinal); for (int keyIndex = 0; (keyIndex < iTable.PrimaryKey.Length); keyIndex = (keyIndex + 1)) { transactionLogItem.Add(iRow[iTable.PrimaryKey[keyIndex], global::System.Data.DataRowVersion.Original]); } DataModel.AddTransaction(iRow, transactionLogItem.ToArray()); iRow.AcceptChanges(); } } } } finally { ClearRowLockList(); DataModel.TransactionLogLock.ExitWriteLock(); DataModel.DataLock.ExitWriteLock(); try { //txn is done remove this txn from the threads stack //in theory the stack should only be accessed from the same thread so dont need a lock //although might want to look at the stack through the DataModelTransaction //via another thread. so lock just to be safe lock (this.dataModelTransactionStack) this.dataModelTransactionStack.Pop(); } catch (Exception ex) { try { global::FluidTrade.Core.EventLog.Information("Error in Commit dataModelTransactionStack.Pop {0}\r\n{1}", ex.Message, ex.StackTrace); } catch { } } } enlistment.Done(); }