/// <summary> /// You should never call this directly, the providers call this method. /// </summary> /// <param name="cmd">The command to enlist into a transaction</param> static public void DeEnlist(IDbCommand cmd) { tgTransactionScope current = GetCurrentTx(); if (current == null || current.option == tgTransactionScopeOption.Suppress) { cmd.Connection.Close(); } }
/// <summary> /// This can be used to get the tgTransactionScopeOption from the current tgTransactionScope (remember transactions can be nested). /// If there is no on-going transaction then tgTransactionScopeOption.None is returned. /// </summary> /// <returns></returns> static public tgTransactionScopeOption GetCurrentTransactionScopeOption() { tgTransactionScope currentTx = GetCurrentTx(); if (currentTx == null) { return(tgTransactionScopeOption.None); } else { return(currentTx.option); } }
/// <summary> /// You should never call this directly, the providers call this method. /// </summary> /// <param name="cmd">The command to enlist into a transaction</param> /// <param name="connectionString">The connection string passed to the CreateIDbConnectionDelegate delegate</param> /// <param name="creator">The delegate previously registered by the provider</param> static public void Enlist(IDbCommand cmd, string connectionString, CreateIDbConnectionDelegate creator) { tgTransactionScope currentTx = GetCurrentTx(); if (currentTx == null || currentTx.option == tgTransactionScopeOption.Suppress) { cmd.Connection = creator(); cmd.Connection.ConnectionString = connectionString; cmd.Connection.Open(); } else { Transaction tx = null; if (currentTx.root.transactions.ContainsKey(connectionString)) { tx = currentTx.root.transactions[connectionString] as Transaction; } else { tx = new Transaction(); IDbConnection cn = creator(); cn.ConnectionString = connectionString; cn.Open(); // The .NET framework has a bug in that the IDbTransaction only maintains // a weak reference to the Connection, thus, we put a strong reference // on it. tx.sqlCn = cn; if (_isolationLevel != IsolationLevel.Unspecified) { tx.sqlTx = cn.BeginTransaction(_isolationLevel); } else { tx.sqlTx = cn.BeginTransaction(); } currentTx.root.transactions[connectionString] = tx; } cmd.Connection = tx.sqlTx.Connection; cmd.Transaction = tx.sqlTx; } }
/// <summary> /// Internal method. /// </summary> /// <returns></returns> static private tgTransactionScope GetCurrentTx() { tgTransactionScope tx = null; object o = Thread.GetData(txSlot); if (o != null) { Stack <tgTransactionScope> stack = o as Stack <tgTransactionScope>; if (stack.Count > 0) { tx = stack.Peek(); } } return(tx); }
/// <summary> /// This is the common constructor logic, tx is "this" from the constructor /// </summary> /// <param name="tx"></param> static protected void CommonInit(tgTransactionScope tx) { Stack <tgTransactionScope> stack; // See if our stack is already created (there is only one per thread) object obj = Thread.GetData(txSlot); if (obj == null) { stack = new Stack <tgTransactionScope>(); Thread.SetData(txSlot, stack); } else { stack = (Stack <tgTransactionScope>)obj; } // If this transaction is required we need to set it's root if (tx.option == tgTransactionScopeOption.Required) { foreach (tgTransactionScope esTrans in stack) { // The root can be either a Requires or RequiresNew, and a root always points to // itself, therefore, as long as it's not a Suppress and it's pointing to itself // then we know this the next root up on the stack if (esTrans.option != tgTransactionScopeOption.Suppress && esTrans == esTrans.root) { tx.root = esTrans; break; } } } // If we didn't find a root, then we are by definition the root if (tx.root == null) { tx.root = tx; tx.transactions = new Dictionary <string, Transaction>(); } stack.Push(tx); }
/// <summary> /// You should never call this directly, EntitySpaces calls this internally. /// </summary> /// <param name="commit">Any class that implements ICommittable</param> /// <returns>True if successful</returns> static public bool AddForCommit(ICommittable commit) { tgTransactionScope current = GetCurrentTx(); if (current != null) { if (current.commitList == null) { current.commitList = new List <ICommittable>(); } current.commitList.Add(commit); return(true); } else { return(false); } }
private static DataTable SaveDynamicCollection(tgDataRequest request) { if (request.CollectionSavePacket == null) return null; using (tgTransactionScope scope = new tgTransactionScope()) { NpgsqlCommand cmd = null; bool exception = false; foreach (tgEntitySavePacket packet in request.CollectionSavePacket) { exception = false; cmd = null; switch (packet.RowState) { case tgDataRowState.Added: cmd = Shared.BuildDynamicInsertCommand(request, packet); break; case tgDataRowState.Modified: cmd = Shared.BuildDynamicUpdateCommand(request, packet); break; case tgDataRowState.Deleted: cmd = Shared.BuildDynamicDeleteCommand(request, packet); break; case tgDataRowState.Unchanged: continue; } try { tgTransactionScope.Enlist(cmd, request.ConnectionString, CreateIDbConnectionDelegate); int count; #region Profiling if (sTraceHandler != null) { using (esTraceArguments esTrace = new esTraceArguments(request, cmd, "SaveCollectionDynamic", System.Environment.StackTrace)) { try { count = cmd.ExecuteNonQuery(); ; } catch (Exception ex) { esTrace.Exception = ex.Message; throw; } } } else #endregion Profiling { count = cmd.ExecuteNonQuery(); } if (count < 1) { throw new tgConcurrencyException("Update failed to update any records"); } } catch (Exception ex) { exception = true; request.FireOnError(packet, ex.Message); if (!request.ContinueUpdateOnError) { throw; } } finally { tgTransactionScope.DeEnlist(cmd); cmd.Dispose(); } if (!exception && packet.RowState != tgDataRowState.Deleted && cmd.Parameters != null) { foreach (NpgsqlParameter param in cmd.Parameters) { switch (param.Direction) { case ParameterDirection.Output: case ParameterDirection.InputOutput: packet.CurrentValues[param.SourceColumn] = param.Value; break; } } } } scope.Complete(); } return null; }
private static DataTable SaveDynamicCollection_InsertsUpdates(tgDataRequest request) { DataTable dataTable = CreateDataTable(request); using (tgTransactionScope scope = new tgTransactionScope()) { using (SQLiteDataAdapter da = new SQLiteDataAdapter()) { da.AcceptChangesDuringUpdate = false; da.ContinueUpdateOnError = request.ContinueUpdateOnError; SQLiteCommand cmd = null; if (!request.IgnoreComputedColumns) { da.RowUpdated += new EventHandler<System.Data.Common.RowUpdatedEventArgs>(OnRowUpdated); } foreach (tgEntitySavePacket packet in request.CollectionSavePacket) { if (packet.RowState != tgDataRowState.Added && packet.RowState != tgDataRowState.Modified) continue; DataRow row = dataTable.NewRow(); dataTable.Rows.Add(row); switch (packet.RowState) { case tgDataRowState.Added: cmd = da.InsertCommand = Shared.BuildDynamicInsertCommand(request, packet); SetModifiedValues(request, packet, row); break; case tgDataRowState.Modified: cmd = da.UpdateCommand = Shared.BuildDynamicUpdateCommand(request, packet); SetOriginalValues(request, packet, row, false); SetModifiedValues(request, packet, row); row.AcceptChanges(); row.SetModified(); break; } request.Properties["tgDataRequest"] = request; request.Properties["esEntityData"] = packet; dataTable.ExtendedProperties["props"] = request.Properties; DataRow[] singleRow = new DataRow[1]; singleRow[0] = row; try { tgTransactionScope.Enlist(cmd, request.ConnectionString, CreateIDbConnectionDelegate); #region Profiling if (sTraceHandler != null) { using (esTraceArguments esTrace = new esTraceArguments(request, cmd, packet, "SaveCollectionDynamic", System.Environment.StackTrace)) { try { da.Update(singleRow); } catch (Exception ex) { esTrace.Exception = ex.Message; throw; } } } else #endregion Profiling { da.Update(singleRow); } if (row.HasErrors) { request.FireOnError(packet, row.RowError); } } finally { tgTransactionScope.DeEnlist(cmd); dataTable.Rows.Clear(); } if (!row.HasErrors && packet.RowState != tgDataRowState.Deleted && cmd.Parameters != null) { foreach (SQLiteParameter param in cmd.Parameters) { switch (param.Direction) { case ParameterDirection.Output: case ParameterDirection.InputOutput: packet.CurrentValues[param.SourceColumn] = param.Value; break; } } } cmd.Dispose(); } } scope.Complete(); } return dataTable; }
private static DataTable SaveDynamicCollection_Deletes(tgDataRequest request) { SQLiteCommand cmd = null; DataTable dataTable = CreateDataTable(request); using (tgTransactionScope scope = new tgTransactionScope()) { using (SQLiteDataAdapter da = new SQLiteDataAdapter()) { da.AcceptChangesDuringUpdate = false; da.ContinueUpdateOnError = request.ContinueUpdateOnError; try { cmd = da.DeleteCommand = Shared.BuildDynamicDeleteCommand(request); tgTransactionScope.Enlist(cmd, request.ConnectionString, CreateIDbConnectionDelegate); DataRow[] singleRow = new DataRow[1]; // Delete each record foreach (tgEntitySavePacket packet in request.CollectionSavePacket) { DataRow row = dataTable.NewRow(); dataTable.Rows.Add(row); SetOriginalValues(request, packet, row, true); row.AcceptChanges(); row.Delete(); singleRow[0] = row; #region Profiling if (sTraceHandler != null) { using (esTraceArguments esTrace = new esTraceArguments(request, cmd, packet, "SaveCollectionDynamic", System.Environment.StackTrace)) { try { da.Update(singleRow); } catch (Exception ex) { esTrace.Exception = ex.Message; throw; } } } else #endregion Profiling { da.Update(singleRow); } if (row.HasErrors) { request.FireOnError(packet, row.RowError); } dataTable.Rows.Clear(); // ADO.NET won't let us reuse the same DataRow } } finally { tgTransactionScope.DeEnlist(cmd); cmd.Dispose(); } } scope.Complete(); } return request.Table; }
private static DataTable SaveStoredProcCollection(tgDataRequest request) { bool needToInsert = false; bool needToUpdate = false; bool needToDelete = false; Dictionary<DataRow, tgEntitySavePacket> rowMapping = null; if (request.ContinueUpdateOnError) { rowMapping = new Dictionary<DataRow, tgEntitySavePacket>(); } //================================================ // Create the DataTable ... //================================================ DataTable dataTable = CreateDataTable(request); foreach (tgEntitySavePacket packet in request.CollectionSavePacket) { DataRow row = dataTable.NewRow(); switch (request.EntitySavePacket.RowState) { case tgDataRowState.Added: SetModifiedValues(request, packet, row); dataTable.Rows.Add(row); if (request.ContinueUpdateOnError) rowMapping[row] = packet; break; case tgDataRowState.Modified: SetOriginalValues(request, packet, row, false); SetModifiedValues(request, packet, row); dataTable.Rows.Add(row); row.AcceptChanges(); row.SetModified(); if (request.ContinueUpdateOnError) rowMapping[row] = packet; break; case tgDataRowState.Deleted: SetOriginalValues(request, packet, row, true); dataTable.Rows.Add(row); row.AcceptChanges(); row.Delete(); if (request.ContinueUpdateOnError) rowMapping[row] = packet; break; } } if (Shared.HasUpdates(dataTable.Rows, out needToInsert, out needToUpdate, out needToDelete)) { using (MySqlDataAdapter da = new MySqlDataAdapter()) { da.AcceptChangesDuringUpdate = false; MySqlCommand cmd = null; if (needToInsert) da.InsertCommand = cmd = Shared.BuildStoredProcInsertCommand(request); if (needToUpdate) da.UpdateCommand = cmd = Shared.BuildStoredProcUpdateCommand(request); if (needToDelete) da.DeleteCommand = cmd = Shared.BuildStoredProcDeleteCommand(request); using (tgTransactionScope scope = new tgTransactionScope()) { if (needToInsert) tgTransactionScope.Enlist(da.InsertCommand, request.ConnectionString, CreateIDbConnectionDelegate); if (needToUpdate) tgTransactionScope.Enlist(da.UpdateCommand, request.ConnectionString, CreateIDbConnectionDelegate); if (needToDelete) tgTransactionScope.Enlist(da.DeleteCommand, request.ConnectionString, CreateIDbConnectionDelegate); try { #region Profiling if (sTraceHandler != null) { using (esTraceArguments esTrace = new esTraceArguments(request, cmd, "SaveCollectionStoredProcedure", System.Environment.StackTrace)) { try { da.Update(dataTable); } catch (Exception ex) { esTrace.Exception = ex.Message; throw; } } } else #endregion Profiling { da.Update(dataTable); } } finally { if (needToInsert) tgTransactionScope.DeEnlist(da.InsertCommand); if (needToUpdate) tgTransactionScope.DeEnlist(da.UpdateCommand); if (needToDelete) tgTransactionScope.DeEnlist(da.DeleteCommand); } scope.Complete(); } } if (request.ContinueUpdateOnError && dataTable.HasErrors) { DataRow[] errors = dataTable.GetErrors(); foreach (DataRow rowWithError in errors) { request.FireOnError(rowMapping[rowWithError], rowWithError.RowError); } } } return request.Table; }
private static DataTable SaveStoredProcCollection(tgDataRequest request) { if (request.CollectionSavePacket == null) return null; OracleCommand cmdInsert = null; OracleCommand cmdUpdate = null; OracleCommand cmdDelete = null; try { using (tgTransactionScope scope = new tgTransactionScope()) { OracleCommand cmd = null; bool exception = false; foreach (tgEntitySavePacket packet in request.CollectionSavePacket) { cmd = null; exception = false; #region Setup Commands switch (packet.RowState) { case tgDataRowState.Added: if (cmdInsert == null) { cmdInsert = Shared.BuildStoredProcInsertCommand(request, packet); tgTransactionScope.Enlist(cmdInsert, request.ConnectionString, CreateIDbConnectionDelegate); } cmd = cmdInsert; break; case tgDataRowState.Modified: if (cmdUpdate == null) { cmdUpdate = Shared.BuildStoredProcUpdateCommand(request, packet); tgTransactionScope.Enlist(cmdUpdate, request.ConnectionString, CreateIDbConnectionDelegate); } cmd = cmdUpdate; break; case tgDataRowState.Deleted: if (cmdDelete == null) { cmdDelete = Shared.BuildStoredProcDeleteCommand(request, packet); tgTransactionScope.Enlist(cmdDelete, request.ConnectionString, CreateIDbConnectionDelegate); } cmd = cmdDelete; break; case tgDataRowState.Unchanged: continue; } #endregion #region Preprocess Parameters if (cmd.Parameters != null) { foreach (OracleParameter param in cmd.Parameters) { if (param.Direction == ParameterDirection.Output) { param.Value = null; } else { if (packet.CurrentValues.ContainsKey(param.SourceColumn)) { param.Value = packet.CurrentValues[param.SourceColumn]; } else { param.Value = null; } } } } #endregion #region Execute Command try { int count = 0; #region Profiling if (sTraceHandler != null) { using (esTraceArguments esTrace = new esTraceArguments(request, cmd, "SaveCollectionStoredProcedure", System.Environment.StackTrace)) { try { count = cmd.ExecuteNonQuery(); } catch (Exception ex) { esTrace.Exception = ex.Message; throw; } } } else #endregion { count = cmd.ExecuteNonQuery(); } if (count < 1) { throw new tgConcurrencyException("Update failed to update any records"); } } catch (Exception ex) { exception = true; request.FireOnError(packet, ex.Message); if (!request.ContinueUpdateOnError) { throw; } } #endregion #region Postprocess Commands if (packet.RowState != tgDataRowState.Deleted && cmd.Parameters != null) { foreach (OracleParameter param in cmd.Parameters) { switch (param.Direction) { case ParameterDirection.Output: case ParameterDirection.InputOutput: packet.CurrentValues[param.SourceColumn] = param.Value; break; } } } #endregion } scope.Complete(); } } finally { if (cmdInsert != null) tgTransactionScope.DeEnlist(cmdInsert); if (cmdUpdate != null) tgTransactionScope.DeEnlist(cmdUpdate); if (cmdDelete != null) tgTransactionScope.DeEnlist(cmdDelete); } return null; }
/// <summary> /// This is the common constructor logic, tx is "this" from the constructor /// </summary> /// <param name="tx"></param> protected static void CommonInit(tgTransactionScope tx) { Stack<tgTransactionScope> stack; // See if our stack is already created (there is only one per thread) object obj = Thread.GetData(txSlot); if (obj == null) { stack = new Stack<tgTransactionScope>(); Thread.SetData(txSlot, stack); } else { stack = (Stack<tgTransactionScope>)obj; } // If this transaction is required we need to set it's root if (tx.option == tgTransactionScopeOption.Required) { foreach (tgTransactionScope esTrans in stack) { // The root can be either a Requires or RequiresNew, and a root always points to // itself, therefore, as long as it's not a Suppress and it's pointing to itself // then we know this the next root up on the stack if (esTrans.option != tgTransactionScopeOption.Suppress && esTrans == esTrans.root) { tx.root = esTrans; break; } } } // If we didn't find a root, then we are by definition the root if (tx.root == null) { tx.root = tx; tx.transactions = new Dictionary<string, Transaction>(); } stack.Push(tx); }