/// <summary>
        /// Executes the provided transaction
        /// </summary>
        private TransactionResponse ExecuteNextTransaction(CancellationToken token, PendingTransaction transaction)
        {
            Validation.IsNotNull(token, "token");
            Validation.IsNotNull(transaction, "transaction");

            token.ThrowIfCancellationRequested();

            var success        = true;
            var commandResults = new ListAtom();

            transaction.State = TransactionState.Executing;
            var sqlTransaction = _connection.BeginTransaction();

            try
            {
                using (var it = transaction.DbCommands.GetEnumerator())
                {
                    while (it.MoveNext())
                    {
                        var dbCommand = it.Current.CastAs <DictionaryAtom>();
                        if (!success)
                        {
                            continue;
                        }
                        var resultSet = ExecuteProcedure(dbCommand);
                        if (resultSet == null || (resultSet.ContainsKey("success") && !resultSet.GetBool("success")))
                        {
                            success = false;
                        }

                        commandResults.Add(resultSet ?? new DictionaryAtom());
                    }
                }
            }
            catch (SqlException ex)
            {
                ex.Handle(ExceptionHandlingOptions.RecordOnly, _log);
                success = false;
            }
            finally
            {
                TryRollbackOrCommit(sqlTransaction, success);
            }

            SetResultSetSuccess(commandResults, success);

            return(new TransactionResponse
            {
                Success = success,
                CommandResults = commandResults
            });
        }
        /// <summary>
        /// Executes the transaction
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="data"></param>
        public virtual void PerformTransaction(EventCallback <RealmEventArgs> callback, DictionaryAtom data)
        {
            Validation.IsNotNull(callback, "callback");
            Validation.Validate(_currentTransaction.State == TransactionState.Building);

            _currentTransaction.Callback            = callback;
            _currentTransaction.TransactionCallback = OnTransactionComplete;
            _currentTransaction.Data = data;
            _pendingTransactions.Add(_transactionId, _currentTransaction);

            _loadBalancer.ExecuteTransaction(_currentTransaction);

            _currentTransaction = null;
        }
        /// <summary>
        /// Submits the given callback with the passed data fields
        /// </summary>
        /// <param name="transaction"></param>
        /// <param name="response"></param>
        private static void IssueCallback(PendingTransaction transaction, TransactionResponse response)
        {
            Validation.IsNotNull(transaction, "transaction");
            Validation.IsNotNull(response, "response");

            if (transaction.Callback == null)
            {
                return;
            }

            transaction.State = TransactionState.Processing;
            transaction.TransactionCallback.Invoke(new DatabaseResponseEventArgs
            {
                Success        = response.Success,
                TransactionId  = transaction.TransactionId,
                CommandResults = response.CommandResults
            });
        }
        public void ExecuteTransaction(PendingTransaction transaction)
        {
            Validation.IsNotNull(transaction, "transaction");
            Validation.IsNotNull(transaction.DbCommands, "transaction.DbCommands");

            _log.InfoFormat(Resources.MSG_TRANS_SUBMIT, transaction.TransactionId);

            Task <TransactionResponse> task        = null;
            CancellationTokenSource    tokenSource = null;

            try
            {
                tokenSource = new CancellationTokenSource();
                task        = Task.Factory.StartNew(() => ExecuteNextTransaction(tokenSource.Token, transaction), tokenSource.Token);

                _tasks.Add(task, tokenSource);
                task.Wait(tokenSource.Token);

                IssueCallback(transaction, task.Result);

                _log.InfoFormat(Resources.MSG_TRANS_COMPLETE, transaction.TransactionId, task.Status);
            }
            catch (AggregateException ex)
            {
                _log.InfoFormat(Resources.MSG_TRANS_CANCELLED, transaction.TransactionId);
                ex.InnerException.Handle(ExceptionHandlingOptions.RecordAndThrow, _log);
            }
            catch (Exception ex)
            {
                ex.Handle(ExceptionHandlingOptions.RecordAndThrow, _log);
            }
            finally
            {
                if (task != null)
                {
                    if (_tasks.ContainsKey(task))
                    {
                        _tasks.Remove(task);
                    }
                    task.Cancel(tokenSource);
                }
            }
        }
 /// <summary>
 /// Starts a new transaction set
 /// </summary>
 /// <returns></returns>
 public virtual int BeginTransaction()
 {
     _transactionId++;
     _currentTransaction = new PendingTransaction(this, _transactionId);
     return(_transactionId);
 }