Пример #1
0
        public void ProcessBatch()
        {
            bool needToLeave = false;

            busy = true;


            try
            {
                //  used to block the Terminate from BizTalk
                if (!this.control.Enter())
                {
                    needToLeave = false;
                    return;
                }

                needToLeave = true;

                StateSettings stateSettings = new StateSettings();
                stateSettings.FindFirst   = this.properties.FirdFirst;
                stateSettings.WorkingFeed = this.properties.FirstFeed;
                stateSettings.Id          = atomState.LastEntryId;


                AtomReader atom = new AtomReader(this.properties.Uri, stateSettings, this.properties.SecuritySettings, this.properties.FeedMax);

                Feed   feed    = null;
                bool   discard = atom.IdFound;
                string stateId = atomState.LastEntryId;
                string lastId  = String.Empty;

                while ((feed = atom.NextFeed()) != null && feed.Entries.Count > 0)
                {
                    ManualResetEvent       orderedEvent = null;
                    CommittableTransaction transaction  = null;


                    //using (SyncReceiveSubmitBatch batch = new SyncReceiveSubmitBatch(this.transportProxy, this.control, 1))

                    Entry entry = feed.Entries.PopOrNUll();

                    while (entry != null)
                    {
                        if (discard == false)
                        {
                            orderedEvent = new ManualResetEvent(false);
                            transaction  = new CommittableTransaction();

                            atomState.LastEntryId = entry.Id;
                            atomState.LastUpdated = feed.Updated;
                            atomState.LastFeed    = feed.Uri;

                            SaveState(transaction);

                            using (SingleMessageReceiveTxnBatch batch = new SingleMessageReceiveTxnBatch(this.transportProxy, this.control, transaction, orderedEvent))
                            {
                                batch.SubmitMessage(CreateMessage(entry));
                                batch.Done();

                                orderedEvent.WaitOne();
                            }
                        }


                        if (stateId == entry.Id)
                        {
                            discard = false;
                        }

                        entry = feed.Entries.PopOrNUll();
                    }
                }



                //  no exception in Done so we will be getting a BatchComplete which will do the necessary Leave
                needToLeave = false;
            }
            catch (MaxDeepthException deepth)
            {
                this.transportProxy.ReceiverShuttingdown(this.properties.Uri, deepth);
            }
            catch (InvalidConfiguration arg)
            {
                this.transportProxy.ReceiverShuttingdown(this.properties.Uri, arg);
            }
            catch (WebException ex)
            {
                this.transportProxy.ReceiverShuttingdown(this.properties.Uri, ex);
            }
            catch (Exception e)
            {
                this.transportProxy.SetErrorInfo(e);
            }
            finally
            {
                busy = false;
                //  if this is true there must have been some exception in or before Done
                if (needToLeave)
                {
                    this.control.Leave();
                }
            }
        }
Пример #2
0
        public void SubmitBatch()
        {
            bool needToLeave = false;

            CommittableTransaction transaction = null;

            try
            {
                //  used to block the Terminate from BizTalk
                if (!this.control.Enter())
                {
                    needToLeave = false;
                    return;
                }
                needToLeave = true;

                ManualResetEvent orderedEvent = new ManualResetEvent(false);

                string connectionString = this.properties.ConnectionString;
                string cmdText          = this.properties.CmdText;
                string rootElementName  = "Root";

                MemoryStream stream = new MemoryStream();

                bool dataAvailable = false;

                //  Create the System.Transactions transaction
                transaction = new CommittableTransaction();

                //  Explicit interop with COM+ - this should not be necessary in future (on SQL 2005 for example)
                using (TransactionScope ts = new TransactionScope(transaction, TimeSpan.FromHours(1), EnterpriseServicesInteropOption.Full))
                {
                    //  The connection is created inside the TransactionScope so the database will be included in the transaction
                    using (SqlConnection connection = new SqlConnection(connectionString))
                    {
                        connection.Open();

                        SqlCommand command = new SqlCommand(cmdText, connection);

                        //  The Encoding on the writer should be consistent with the BizTalk message.
                        //  If you change this to UTF8 then you should change the BizTalk message CharSet to UTF8.

                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Encoding           = Encoding.Unicode;
                        settings.Indent             = true;
                        settings.OmitXmlDeclaration = false;

                        using (XmlWriter writer = XmlTextWriter.Create(stream, settings))
                        {
                            writer.WriteStartDocument();

                            //  Add the root element because the reader form the database doesn't
                            //  include the root element for the xml - it's just rows
                            writer.WriteStartElement(rootElementName);

                            //  WriteNode is a little opaque checking the size of the underlying stream
                            //  is a simple way to see whether any data was retrieved.
                            writer.Flush();
                            long beforeSize = stream.Length;

                            using (XmlReader reader = command.ExecuteXmlReader())
                            {
                                while (!reader.EOF)
                                {
                                    writer.WriteNode(reader, true);
                                }
                            }

                            writer.Flush();
                            long afterSize = stream.Length;

                            //  we only want to add a new message to BizTalk if the reader actually returned anything
                            dataAvailable = (afterSize > beforeSize);

                            writer.WriteEndElement();
                        }
                    }

                    //  An exception will have skipped this next line
                    ts.Complete();
                }

                //  Typically when polling like this you would want to loop checking dataAvailable and only
                //  return to the sleep state when there is no data to feed into BizTalk.
                //
                //  For simplicity this is not shown here. If this is written like this, consideration should also be
                //  given to the .NET thread pool. Sitting on a .NET thread pool thread for an extended period can
                //  result in scale out problems. It is advisable to build some type of yield into the loop, for example
                //  having the worker function BeginInvoke itself if there is dataAvailable might work better than
                //  a simple while loop.

                if (dataAvailable)
                {
                    //  Remember to Seek the stream or we won't get the data
                    stream.Seek(0, SeekOrigin.Begin);

                    //  Note the batch has been given the CommittableTransaction and it will take responsibility for Commit
                    using (Batch batch = new SingleMessageReceiveTxnBatch(this.transportProxy, this.control, transaction, orderedEvent))
                    {
                        batch.SubmitMessage(CreateMessage(stream));
                        batch.Done();
                    }

                    orderedEvent.WaitOne();
                }
                else
                {
                    //  No data so no batch but in a database scenario (like this) we might still wish to Commit.
                    //  Other transactional adapters might choose to Rollback in this circumstance.
                    transaction.Commit();
                }

                //  no exception in Done so we will be getting a BatchComplete which will do the necessary Leave
                needToLeave = false;
            }
            catch (Exception e)
            {
                this.transportProxy.SetErrorInfo(e);

                if (transaction != null)
                {
                    transaction.Rollback();
                }
            }
            finally
            {
                //  if this is true there must have been some exception in or before Done
                if (needToLeave)
                {
                    this.control.Leave();
                }
            }
        }