This is the EntitySpaces ADO.NET connection based transaction class that mimics the System.Transactions.TransactionScope class.
EntitySpaces supports two transactions models, connection based via this class (tgTransactionScope) and the new System.Transactions.TransactionScope. Some databases such as Microsoft Access don't support the new System.Transactions.TransactionScope class. And still there are other cases where the System.Transactions.TransactionScope class cannot be used as is the case with a lot of hosting companies. Thus EntitySpaces provides a very nice ADO.NET connection based transaction handler. The Syntax should be as follows: using (tgTransactionScope scope = new tgTransactionScope()) { // Logic here ... scope.Complete(); // last line of using statement } Note that if an exception is thrown scope.Complete will not be called, and the transaction upon leaving the using statement will be rolled back. You indicate whether you want the provider to use the tgTransactionScope or the System.Transactions.TransactionScope class in your .config file. Notice in the config file setting below that providerClass="DataProvider". This indicates that you want to use the tgTransactionScope class, use providerClass="DataProviderEnterprise" to use System.Transactions.TransactionScope. <add name="SQL" providerMetadataKey="esDefault" sqlAccessType="DynamicSQL" provider="Tiraggo.SqlClientProvider" providerClass="DataProvider" connectionString="User ID=sa;Password=griffinski;Initial Catalog=Northwind;Data Source=localhost" databaseVersion="2005"/>
Inheritance: IDisposable
Beispiel #1
0
        /// <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();
            }
        }
Beispiel #2
0
        /// <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);
            }
        }
Beispiel #3
0
        /// <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;
            }
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <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);
            }
        }
Beispiel #7
0
        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;
        }
Beispiel #8
0
        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;
        }
Beispiel #9
0
        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;
        }
Beispiel #10
0
        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;
        }
Beispiel #11
0
        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;
        }
Beispiel #12
0
        /// <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);
        }