コード例 #1
0
        //  This function is running inside the TransactionScope and the SqlConnection should pick up the current transaction
        //  This will attempt to execute a stored procedure with a single parameter called @Data of type ntext
        private void SendMessage(IBaseMessage message, TransactionalTransmitProperties properties)
        {
            TextReader reader  = new StreamReader(message.BodyPart.Data);
            string     msgText = reader.ReadToEnd();

            string storedProcedureName = properties.CmdText;
            string connectionString    = properties.ConnectionString;

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                SqlCommand command = new SqlCommand(storedProcedureName, connection);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@Data", msgText));
                command.ExecuteScalar();
            }
        }
コード例 #2
0
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //  thread per endpoint batch
        private void BatchWorker(string outboundTransportLocation, ArrayList messages)
        {
            //  we did an enter for every message - so we should ensure we have a correspending leave
            int leaveCount = messages.Count;

            try
            {
                //  all the messages in this batch should have the same properties - so just take the first one
                IBaseMessage                    firstMessage        = (IBaseMessage)messages[0];
                SystemMessageContext            firstMessageContext = new SystemMessageContext(firstMessage.Context);
                TransactionalTransmitProperties properties          = new TransactionalTransmitProperties(firstMessageContext.OutboundTransportLocation);

                string config = (string)firstMessage.Context.Read("AdapterConfig", this.propertyNamespace);
                if (config != null)
                {
                    // There is a configuration DOM so we are doing a Static Send
                    XmlDocument locationConfigDom = new XmlDocument();
                    locationConfigDom.LoadXml(config);
                    properties.LocationConfiguration(locationConfigDom);
                }
                else
                {
                    // Add dynamic send here
                }

                foreach (IBaseMessage message in messages)
                {
                    CommittableTransaction transaction = null;

                    try
                    {
                        //  create the System.Transactions transaction - this is not yet a DTC transaction
                        transaction = new CommittableTransaction();

                        //  give the CommittableTransaction to the batch and it will take the responsibility to Commit it.
                        //  the TransactionInterop.GetDtcTransaction call inside the base TxnBase class actually causes the
                        //  DTC transaction to be created - this can be observed in the COM+ Explorer while debugging this code
                        using (Batch batch = new TransactionalDeleteBatch(this.transportProxy, this.control, transaction))
                        {
                            //  note the options EnterpriseServicesInteropOption.Full in the future when resource managers
                            //  understand light weight transactions this might not be necessary but we need it for now
                            using (TransactionScope ts = new TransactionScope(transaction, TimeSpan.FromHours(1), EnterpriseServicesInteropOption.Full))
                            {
                                SendMessage(message, properties);

                                //  an exception will skip this next line
                                ts.Complete();
                            }

                            //  IMPORTANT: a Delete is part of the same transaction as the send operation
                            batch.DeleteMessage(message);

                            //  IMPORTANT: if there was a response to submit it would be added here
                            //  - in the same batch and same transaction as the Delete

                            batch.Done();
                        }
                    }
                    catch (Exception e)
                    {
                        // in this scenario we will explicitly Rollback the transaction on failure
                        if (transaction != null)
                        {
                            transaction.Rollback();
                        }

                        //  Remember to set the exception on the message itself - this will now appear in tracking in addition to the EventLog
                        message.SetErrorInfo(e);

                        //  Any failures need to be retried - but the change of state back on BizTalk is outside of the transaction
                        //  that has been used to attempt to send the message - after all that transaction will undoubtedly get rollback with the failure.
                        //  We say this batch is "non-transactional" from the adapter's point of view - though internally in BizTalk its still a transaction.
                        using (TransmitResponseBatch batch = new TransmitResponseBatch(this.transportProxy, new TransmitResponseBatch.AllWorkDoneDelegate(AllWorkDone)))
                        {
                            batch.Resubmit(message, false, null);
                            batch.Done();
                        }
                    }

                    // an exception will skip this line - an exception means the Done hasn't been called or was successful so we have a leave to do
                    leaveCount--;
                }
            }
            catch (Exception e)
            {
                this.transportProxy.SetErrorInfo(e);
            }
            finally
            {
                // perform any remain leaves - hopefully none - if everything was successful then leaveCount will be 0
                for (int i = 0; i < leaveCount; i++)
                {
                    this.control.Leave();
                }
            }
        }