Beispiel #1
0
        /// <summary>
        /// Execute the batch and catch the errors.
        /// </summary>
        /// <param name="batch">A batch of commands to be executed.</param>
        /// <returns>Any exceptions from executing the batch, null if there are none.</returns>
        public static bool Execute(Batch batch, Control owner, BatchExceptionEventHandler batchExceptionEventHandler)
        {
            bool success = false;

            // Execute the batch and process the results.
            if (batch != null)
            {
                success = true;

                try
                {
                    // Execute the batch on the server and process the results.
                    ClientMarketData.Execute(batch);
                }
                catch (BatchException batchException)
                {
                    success = false;

                    owner.BeginInvoke(batchExceptionEventHandler, new object[] { typeof(ClientMarketData),
                                                                                 new BatchExceptionEventArgs(batchException) });
                }
            }

            return(success);
        }
Beispiel #2
0
 /// <summary>
 /// Event trigger when any record in the data model has changed.
 /// </summary>
 /// <param name="sender">Object originating the event.</param>
 public static void OnEndMerge(object sender)
 {
     // If a handler has been associated with this event, invoke it.
     if (ClientMarketData.EndMerge != null)
     {
         ClientMarketData.EndMerge(sender, EventArgs.Empty);
     }
 }
Beispiel #3
0
 /// <summary>
 /// Required method for Designer support - do not modify
 /// the contents of this method with the code editor.
 /// </summary>
 private void InitializeComponent()
 {
     this.components = new System.ComponentModel.Container();
     System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(AdvertisementViewer));
     this.clientClientMarketData = new MarkThree.Guardian.Client.ClientMarketData(this.components);
     this.SuspendLayout();
     //
     // AdvertisementViewer
     //
     this.Name = "AdvertisementViewer";
     this.ResumeLayout(false);
 }
Beispiel #4
0
        /// <summary>
        /// Execute a command batch and synchronizes the client data model with the newer records from the server.
        /// </summary>
        public static void Execute(Batch batch)
        {
            // This 'try' block will insure that the mutual exclusion locks are released.
            try
            {
                // Make sure only one thread at a time tries to refresh the data model.
                ClientMarketData.clientDataMutex.WaitOne();

                // Switching credentials without exiting the application will force the data model to be cleared and the row
                // counting to begin at zero again.  That is, it effectively resets the client data model.
                if (ClientMarketData.isReset)
                {
                    ClientMarketData.isReset    = false;
                    ClientMarketData.rowVersion = 0;
                    ClientMarketData.Clear();
                }

                // IMPORTANT CONCEPT: The rowVersion keeps track of the state of the client in-memory database. The server
                // returns a value for us to use on the next cycle.
                long rowVersion = ClientMarketData.rowVersion;

                // IMPORTANT CONCEPT:  Executing the 'GetClientMarketData' with a rowVersion returns to the client a DataSet
                // with only records that are the same age or younger than the rowVersion. This reduces the traffic on the
                // network to include only the essential records.  We are also merging it with the current ClientMarketData,
                // which adds new records and records that were deleted by the server.
                AssemblyPlan    assembly            = batch.Assemblies.Add("Server Market Data");
                TypePlan        type                = assembly.Types.Add("MarkThree.Guardian.Server.ServerMarketData");
                TransactionPlan transaction         = batch.Transactions.Add();
                MethodPlan      method              = transaction.Methods.Add(type, "Reconcile");
                Parameter       rowVersionParameter = method.Parameters.Add(new InputParameter("rowVersion", rowVersion));

                // Execute the the command to get the incremental changes from the server.
                WebTransactionProtocol.Execute(batch);

                // This is the updated data model information returned from the server.
                ArrayList reconciledData = (ArrayList)method.Parameters.Return.Value;

                // Optimization: Don't merge the results if there's nothing to merge.
                if (reconciledData != null)
                {
                    // IMPORTANT CONCEPT: Since the results will still be on the server if the client misses a refresh
                    // cycle, we take the attitude that thBzis update process doesn't have to wait for locks. That is, if we
                    // can't get all the tables locked quickly, we'll just wait until the next refresh period to get the
                    // results. This effectively prevents deadlocking on the client. Make sure all the tables are locked
                    // before populating them.
                    foreach (TableLock tableLock in ClientMarketData.TableLocks)
                    {
                        tableLock.AcquireWriterLock(ClientTimeout.LockWait);
                    }

                    // IMPORTANT CONCEPT: This broadcast can be used to set up conditions for the data event handlers. Often,
                    // optimizing algorithms will be used to consolidate the results of a merge.  This will allow the event
                    // driven logic to clear previous results and set up initial states for handling the bulk update of data.
                    ClientMarketData.OnBeginMerge(typeof(ClientMarketData));

                    // IMPORANT CONCEPT:  Once all the write locks have been obtained, we can merge the results.  This will
                    // trigger the events associated with the tables for updated and deleted rows.  Note that this 'Merge'
                    // method has different characteristics than the original one provided by Microsoft (that is, this one
                    // works).
                    ClientMarketData.rowVersion = MarketData.Merge(reconciledData);

                    // IMPORTANT CONCEPT: When the merge is complete, this will broadcast an event which allows optimization code
                    // to consolidate the results, examine the changed values and update reports based on the changed data.
                    ClientMarketData.OnEndMerge(typeof(ClientMarketData));
                }
            }
            finally
            {
                // No matter what happens above, we need to release the locks acquired above.
                foreach (TableLock tableLock in ClientMarketData.TableLocks)
                {
                    if (tableLock.IsWriterLockHeld)
                    {
                        tableLock.ReleaseWriterLock();
                    }
                }

                // Other threads can now request a refresh of the data model.
                ClientMarketData.clientDataMutex.ReleaseMutex();
            }

            // Throw a specialized exception if the server returned any errors in the Batch structure.
            if (batch.HasExceptions)
            {
                throw new BatchException(batch);
            }
        }