/// <summary> /// This is the core execution function, it accept a simple functor that will accept a sqlcommand /// the command is created in the core of the function so it really care of all the standard /// burden of creating connection, creating transaction and enlist command into a transaction. /// </summary> /// <param name="functionToExecute">The delegates that really executes the command.</param> internal static void Execute(Action <DbCommand, DbProviderFactory> functionToExecute) { DbProviderFactory factory = GetFactory(); using (GlobalTransactionManager.TransactionToken token = CreateConnection()) { ConnectionData connectionData = (ConnectionData)token.GetFromTransactionContext(GetKeyFromConnName(String.Empty)); try { using (DbCommand command = factory.CreateCommand()) { command.CommandType = CommandType.Text; command.Connection = connectionData.Connection; command.Transaction = connectionData.CurrentTransaction; functionToExecute(command, factory); } } catch { //There is an exception, I doom the transaction. token.Doom(); throw; } } }
public void ContextNestedWithTwoTransactionLast() { GlobalTransactionManager.BeginTransaction(); GlobalTransactionManager.BeginTransaction(); GlobalTransactionManager.TransactionToken token = GlobalTransactionManager.Enlist(Nope); GlobalTransactionManager.TransactionContext.Set("key", "test", 1); Assert.That(token.GetFromTransactionContext("key"), Is.EqualTo("test")); }
/// <summary> /// This is the Connetion creation function, this function should enlist in the /// current transaction as well reusing the same connection for all the call /// inside a global transaction to consume less resources. /// </summary> /// <param name="connectionName"></param> /// <returns></returns> internal static GlobalTransactionManager.TransactionToken CreateConnection(string connectionName) { ConnectionData newConnData = null; if (GlobalTransactionManager.IsInTransaction) { //We are in a transaction, check if at current connection stack level there is a connection data. Object connData = GlobalTransactionManager.TransactionContext.Get(GetKeyFromConnName(connectionName)); if (null != connData) { //We already created the connection for this database in this transaction. return(GlobalTransactionManager.Enlist(DoNothing)); } //There is not a transaction in the current transaction stack level, are we in nested transaction? if (GlobalTransactionManager.TransactionsCount > 1) { //The only connection data valid is the one at the first level, lets check if it is present. connData = GlobalTransactionManager.TransactionContext.Get(GetKeyFromConnName(connectionName), 0); if (null == connData) { //We never created the connection data newConnData = new ConnectionData(connectionName); GlobalTransactionManager.TransactionContext.Set(GetKeyFromConnName(connectionName), newConnData, 0); GlobalTransactionManager.Enlist(newConnData.CloseConnection, 0); } else { newConnData = (ConnectionData)connData; } GlobalTransactionManager.TransactionToken lasttoken = null; //Now we have the connection data, we need to store this connection data in each connection that is active and //that still not have start a transaction for (Int32 Ix = 1; Ix < GlobalTransactionManager.TransactionsCount; ++Ix) { if (GlobalTransactionManager.TransactionContext.Get(GetKeyFromConnName(connectionName), Ix) == null) { //In this step of the stack there is no ConnectionData, store and increase the transaction newConnData.BeginNestedTransaction(); lasttoken = GlobalTransactionManager.Enlist(newConnData.CloseConnection, Ix); lasttoken.SetInTransactionContext(GetKeyFromConnName(connectionName), newConnData); } } //Return the last token, the one corresponding to the current transaction level. return(lasttoken); } } //We are not in nested transaction and there is not connection data, create for the first time newConnData = new ConnectionData(connectionName); GlobalTransactionManager.TransactionToken token = GlobalTransactionManager.Enlist(newConnData.CloseConnection); token.SetInTransactionContext(GetKeyFromConnName(connectionName), newConnData); return(token); }
public void EnlistWithoutATransactionRollback() { Action <Boolean> mock = mockRepository.CreateMock <Action <Boolean> >(); mock(false); //Sets the expectation mockRepository.ReplayAll(); using (GlobalTransactionManager.TransactionToken token = GlobalTransactionManager.Enlist(mock)) { token.Doom(); //Do something, the important thing is that the delegate is called because we have //not a transaction active. } }
/// <summary> /// Execute a sqlquery. /// </summary> /// <param name="q"></param> /// <param name="executionCore"></param> public static void Execute(SqlQuery q, Action executionCore) { using (GlobalTransactionManager.TransactionToken token = CreateConnection(q.ConnectionStringName)) { ConnectionData connectionData = (ConnectionData)token.GetFromTransactionContext( GetKeyFromConnName(q.ConnectionStringName)); try { using (q.Command) { q.Command.Connection = connectionData.Connection; q.Command.Transaction = connectionData.CurrentTransaction; q.Command.CommandText = q.Query; executionCore(); } } catch { token.Doom(); throw; } } }