//[ValidateAntiForgeryToken] public ActionResult Edit([Bind(Include = "Order,SKU,Id,OrderKey,SKUId,DesignName,ComponentSKU,FinishedSKU,OrderDate,RequirementDate,ResolveDate1,ActualReleaseDate1,SetPlanDate2,PutawayDate2,SetPlanDate3,PutawayDate3,SetPlanDate4,PutawayDate4,SetPlanDate5,DeliveryDate5,PutawayDate5,SetPlanDate6,ActualStartDate6,ActualCompletedDate6,Remark,Status,OrderId,BomComponentId,ParentBomComponentId,CreatedUserId,CreatedDateTime,LastEditUserId,LastEditDateTime")] AssemblyPlan assemblyPlan) { if (ModelState.IsValid) { assemblyPlan.ObjectState = ObjectState.Modified; _assemblyPlanService.Update(assemblyPlan); _unitOfWork.SaveChanges(); if (Request.IsAjaxRequest()) { return(Json(new { success = true }, JsonRequestBehavior.AllowGet)); } DisplaySuccessMessage("Has update a AssemblyPlan record"); return(RedirectToAction("Index")); } var orderRepository = _unitOfWork.Repository <Order>(); ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "OrderKey", assemblyPlan.OrderId); var skuRepository = _unitOfWork.Repository <SKU>(); ViewBag.SKUId = new SelectList(skuRepository.Queryable(), "Id", "Sku", assemblyPlan.SKUId); if (Request.IsAjaxRequest()) { var modelStateErrors = String.Join("", this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors.Select(n => n.ErrorMessage))); return(Json(new { success = false, err = modelStateErrors }, JsonRequestBehavior.AllowGet)); } DisplayErrorMessage(); return(View(assemblyPlan)); }
// GET: AssemblyPlans/Create public ActionResult Create() { AssemblyPlan assemblyPlan = new AssemblyPlan(); //set default value var orderRepository = _unitOfWork.Repository <Order>(); ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "OrderKey"); var skuRepository = _unitOfWork.Repository <SKU>(); ViewBag.SKUId = new SelectList(skuRepository.Queryable(), "Id", "Sku"); return(View(assemblyPlan)); }
//[ValidateAntiForgeryToken] public ActionResult DeleteConfirmed(int id) { AssemblyPlan assemblyPlan = _assemblyPlanService.Find(id); _assemblyPlanService.Delete(assemblyPlan); _unitOfWork.SaveChanges(); if (Request.IsAjaxRequest()) { return(Json(new { success = true }, JsonRequestBehavior.AllowGet)); } DisplaySuccessMessage("Has delete a AssemblyPlan record"); return(RedirectToAction("Index")); }
/// <summary> /// Parse a method from the XML file. /// </summary> /// <param name="methodNode">The node where the method data is found.</param> private void ParseMethod(XmlNode methodNode) { // Keep track of the number of methods read and processed. this.MethodCount++; // Extract the assembly and type information from the method node. These are used to locate an object containing the // method. That is, the server will use 'System.Reflection' to load an assembly with the 'assembly' name, load and // instantiate an object of 'type', then call the named method with the parameters listed. AssemblyPlan assembly = this.batch.Assemblies.Add(methodNode.Attributes["assembly"].Value); TypePlan type = assembly.Types.Add(methodNode.Attributes["type"].Value); // Create a method from the XML data and add it to the transaction. this.transaction.Methods.Add(type, LoadMethod(methodNode)); }
// GET: AssemblyPlans/Delete/5 public ActionResult Delete(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } AssemblyPlan assemblyPlan = _assemblyPlanService.Find(id); if (assemblyPlan == null) { return(HttpNotFound()); } return(View(assemblyPlan)); }
public IEnumerable <AssemblyPlan> GenerateAssemblyPlan(int orderId) { List <AssemblyPlan> list = new List <AssemblyPlan>(); var order = this.Find(orderId); order.Status = 2; order.AuditDate = DateTime.Now; this.Update(order); list = this._assemblyservice.Queryable().Where(x => x.OrderId == orderId).ToList(); if (list.Count > 0) { return(list); } else { var orderdetails = _orderdetailrepository.Queryable().Include(x => x.Order).Where(x => x.OrderId == orderId).ToList(); foreach (var item in orderdetails) { var bomlist = _bomrepository.Queryable().Include(s => s.SKU).Where(x => x.FinishedSKU == item.ProductionSku && x.SKU.SKUGroup == "部套").ToList(); foreach (var component in bomlist) { AssemblyPlan plan = new AssemblyPlan(); plan.OrderId = item.OrderId; plan.OrderKey = item.OrderKey; plan.OrderDate = item.Order.OrderDate; plan.RequirementDate = item.Order.PlanFinishDate; plan.ComponentSKU = component.ComponentSKU; plan.BomComponentId = component.Id; plan.ParentBomComponentId = component.ParentComponentId; plan.FinishedSKU = component.FinishedSKU; plan.DesignName = component.DesignName; plan.SKUId = component.SKUId; list.Add(plan); } } this._assemblyservice.InsertRange(list); } return(list); }
// GET: AssemblyPlans/Edit/5 public ActionResult Edit(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } AssemblyPlan assemblyPlan = _assemblyPlanService.Find(id); if (assemblyPlan == null) { return(HttpNotFound()); } var orderRepository = _unitOfWork.Repository <Order>(); ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "OrderKey", assemblyPlan.OrderId); var skuRepository = _unitOfWork.Repository <SKU>(); ViewBag.SKUId = new SelectList(skuRepository.Queryable(), "Id", "Sku", assemblyPlan.SKUId); return(View(assemblyPlan)); }
static int Main(string[] args) { // If this flag is set during the processing of the file, the program will exit with an error code. bool hasErrors = false; try { // Defaults batchSize = 100; assemblyName = "External Service"; nameSpaceName = "MarkThree.Quasar.External"; // The command line parser is driven by different states that are triggered by the flags read. Unless a flag has been // read, the command line parser assumes that it's reading the file name from the command line. argumentState = ArgumentState.FileName; // Parse the command line for arguments. foreach (string argument in args) { // Decode the current argument into a state change (or some other action). if (argument == "-a") { argumentState = ArgumentState.Assembly; continue; } if (argument == "-b") { argumentState = ArgumentState.BatchSize; continue; } if (argument == "-n") { argumentState = ArgumentState.NameSpace; continue; } if (argument == "-i") { argumentState = ArgumentState.FileName; continue; } // The parsing state will determine which variable is read next. switch (argumentState) { case ArgumentState.Assembly: assemblyName = argument; break; case ArgumentState.BatchSize: batchSize = Convert.ToInt32(argument); break; case ArgumentState.FileName: fileName = argument; break; case ArgumentState.NameSpace: nameSpaceName = argument; break; } // The default state is to look for the input file name on the command line. argumentState = ArgumentState.FileName; } // Throw a usage message back at the user if no file name was given. if (fileName == null) { throw new Exception("Usage: Loader.Algorithm -i <FileName>"); } // Open up the file containing all the broker. BrokerReader brokerReader = new BrokerReader(fileName); // Loading the database involves creating a batch of commands and sending them off as a transaction. This gives // the server a chance to pipeline a large chunk of processing, without completely locking up the server for the // entire set of data. This will construct a header for the command batch which gives information about which // assembly contains the class that is used to load the data. Batch batch = new Batch(); TransactionPlan transactionPlan = batch.Transactions.Add(); AssemblyPlan assemblyPlan = batch.Assemblies.Add(assemblyName); TypePlan typePlan = assemblyPlan.Types.Add(string.Format("{0}.{1}", nameSpaceName, "Broker")); // Read the file until an EOF is reached. while (true) { // This counter keeps track of the number of records sent. When the batch is full, it's sent to the server to be // executed as a single transaction. int batchCounter = 0; // Read the next broker from the input stream. A 'null' is returned when we've read past the end of file. Broker broker = brokerReader.ReadBroker(); if (broker != null) { // Create a new method from the type information and the name found in the XML file. MethodPlan methodPlan = new MethodPlan("Load"); // Construct a call to the 'Load' method to populate the broker record. methodPlan.Parameters.Add(new InputParameter("brokerId", broker.Symbol)); methodPlan.Parameters.Add(new InputParameter("name", broker.Name)); methodPlan.Parameters.Add(new InputParameter("symbol", broker.Symbol)); // Create a method from the XML data and add it to the transaction. transactionPlan.Methods.Add(typePlan, methodPlan); } // This will check to see if it's time to send the batch. A batch is sent when the 'batchSize' has been // reached, or if the last record has just been converted into a command. if (++batchCounter % batchSize == 0 || broker == null) { WebTransactionProtocol.Execute(batch); batch = new Batch(); transactionPlan = batch.Transactions.Add(); assemblyPlan = batch.Assemblies.Add(assemblyName); typePlan = assemblyPlan.Types.Add(string.Format("{0}.{1}", nameSpaceName, "Broker")); } // If the end of file was reached, break out of the loop and exit the application. if (broker == null) { break; } } } catch (BatchException batchException) { foreach (Exception exception in batchException.Exceptions) { Console.WriteLine(exception.Message); } hasErrors = true; } catch (Exception exception) { // Show the system error and exit with an error. Console.WriteLine(exception.Message); hasErrors = true; } // Any errors will cause an abnormal exit. if (hasErrors) { return(1); } // Write a status message when a the file is loaded successfully. Console.WriteLine(String.Format("{0} Data: Brokers, Loaded", DateTime.Now.ToString("u"))); // If we reached here, the file was imported without issue. return(0); }
/// <summary> /// Begins the task of applying the changes in the form to the data model. /// </summary> private void PostThread(object parameter) { // Extract the parameters from the threads parameter. object[] parameters = (object[])parameter; bool exitDialog = (bool)parameters[0]; SourceOrder sourceOrder = (SourceOrder)parameters[1]; // This batch will collect the information needed to execute a complex transaction on the server. The first part of // the batch sets up the transaction: the assembly where the types and methods are found. It also sets up a // transaction for a complex operation. In this case, the transaction is not that complex, just a single method to be // executed. Batch batch = new Batch(); AssemblyPlan assembly = batch.Assemblies.Add("Trading Service"); TypePlan type = assembly.Types.Add("MarkThree.Guardian.Trading.SourceOrder"); TransactionPlan transaction = batch.Transactions.Add(); MethodPlan methodPlan = transaction.Methods.Add(type, "Insert"); // These are the parameters used to create a Source Order. The Working Order will be created implicitly. methodPlan.Parameters.Add(new InputParameter("blotterId", this.blotter.BlotterId)); methodPlan.Parameters.Add(new InputParameter("isBrokerMatch", sourceOrder.IsBrokerMatch)); methodPlan.Parameters.Add(new InputParameter("isHedgeMatch", sourceOrder.IsHedgeMatch)); methodPlan.Parameters.Add(new InputParameter("isInstitutionMatch", sourceOrder.IsInstitutionMatch)); methodPlan.Parameters.Add(new InputParameter("submissionTypeCode", SubmissionType.UsePeferences)); if (sourceOrder.MaximumVolatility != DBNull.Value) { methodPlan.Parameters.Add(new InputParameter("maximumVolatility", sourceOrder.MaximumVolatility)); } if (sourceOrder.NewsFreeTime != DBNull.Value) { methodPlan.Parameters.Add(new InputParameter("newsFreeTime", sourceOrder.NewsFreeTime)); } methodPlan.Parameters.Add(new InputParameter("orderedQuantity", sourceOrder.Quantity)); methodPlan.Parameters.Add(new InputParameter("orderTypeCode", sourceOrder.OrderTypeCode)); methodPlan.Parameters.Add(new InputParameter("priceTypeCode", PriceType.Market)); methodPlan.Parameters.Add(new InputParameter("securityId", sourceOrder.SecurityId)); methodPlan.Parameters.Add(new InputParameter("settlementId", sourceOrder.SettlementId)); if (sourceOrder.StartTime != DBNull.Value) { methodPlan.Parameters.Add(new InputParameter("startTime", sourceOrder.StartTime)); } if (sourceOrder.StopTime != DBNull.Value) { methodPlan.Parameters.Add(new InputParameter("stopTime", sourceOrder.StopTime)); } methodPlan.Parameters.Add(new InputParameter("timeInForceCode", TimeInForce.Day)); // This will execute the command on the server and return any exceptions. BatchException batchException = null; try { // Execute the batch. ClientMarketData.Execute(batch); } catch (BatchException exception) { // Any exceptions will be captured here and passed on to the foreground. batchException = exception; } // Call the foreground thread with the results of executing the batch on the server. Also, in some cases the dialog is // going to be dismissed when the server data model has finished updating successfully. Pass on the flag to the // foreground that will indicate whether the form is closed once the results are processed. BeginInvoke(this.postEndDelegate, new object[] { exitDialog, batchException }); }
private void DeclineTrade(object parameter) { bool isBatchValid = true; Batch batch = new Batch(); MethodPlan method = null; try { // Lock the tables. System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); ClientMarketData.MatchLock.AcquireReaderLock(ClientTimeout.LockWait); ClientMarketData.OrderTypeLock.AcquireReaderLock(ClientTimeout.LockWait); ClientMarketData.SecurityLock.AcquireReaderLock(ClientTimeout.LockWait); ClientMarketData.WorkingOrderLock.AcquireReaderLock(ClientTimeout.LockWait); // Find the Match record. ClientMarketData.MatchRow matchRow = ClientMarketData.Match.FindByMatchId(this.matchId); AssemblyPlan assembly = batch.Assemblies.Add("Core Service"); TypePlan type = assembly.Types.Add("MarkThree.Guardian.Core.Negotiation"); TransactionPlan transaction = batch.Transactions.Add(); method = transaction.Methods.Add(type, "Insert"); method.Parameters.Add(new InputParameter("matchId", matchId)); method.Parameters.Add(new InputParameter("quantity", 0.0m)); method.Parameters.Add(new InputParameter("statusCode", Status.Declined)); } catch (Exception exception) { // Write the error and stack trace out to the debug listener EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace); // This indicates that the batch shouldn't be executed. isBatchValid = false; } finally { // Release the locks. if (ClientMarketData.MatchLock.IsReaderLockHeld) { ClientMarketData.MatchLock.ReleaseReaderLock(); } if (ClientMarketData.OrderTypeLock.IsReaderLockHeld) { ClientMarketData.OrderTypeLock.ReleaseReaderLock(); } if (ClientMarketData.SecurityLock.IsReaderLockHeld) { ClientMarketData.SecurityLock.ReleaseReaderLock(); } if (ClientMarketData.WorkingOrderLock.IsReaderLockHeld) { ClientMarketData.WorkingOrderLock.ReleaseReaderLock(); } System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); } // If the command batch was built successfully, then execute it. If any part of it should fail, cancel the edit and // display the server errors. if (isBatchValid) { try { // Call the web server to rename the object on the database. Note that this method must be called when there // are no locks to prevent deadlocking. That is why it appears in it's own 'try/catch' block. ClientMarketData.Execute(batch); this.negotiationId = (int)method.Parameters.Return.Value; } catch (BatchException batchException) { // Display each error in the batch. foreach (Exception exception in batchException.Exceptions) { Invoke(new MessageDelegate(ShowMessage), exception.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } }
/// <summary> /// Moves a child object from one parent to another. /// </summary> /// <param name="parameter">An array consiting of the target parent, the current parent and the child to be moved.</param> private void MoveChild(object parameter) { // Extract the objects selected by the drag-and-drop operation. object[] parameters = (object[])parameter; MarkThree.Guardian.Object toObject = (MarkThree.Guardian.Object)parameters[0]; MarkThree.Guardian.Object fromObject = (MarkThree.Guardian.Object)parameters[1]; MarkThree.Guardian.Object childObject = (MarkThree.Guardian.Object)parameters[2]; try { // Lock the tables needed for this operation. System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.ObjectTreeLock.AcquireReaderLock(CommonTimeout.LockWait); // It's critical that circular references aren't created, either by accident or design. First, find the object // record associated with the destination node. ClientMarketData.ObjectRow parentRow = ClientMarketData.Object.FindByObjectId(toObject.ObjectId); if (parentRow == null) { throw new Exception("This object has been deleted"); } // This is the object that is being dragged. Find the row ClientMarketData.ObjectRow childRow = ClientMarketData.Object.FindByObjectId(childObject.ObjectId); if (childRow == null) { throw new Exception("This object has been deleted"); } // This will remove the possibility of a circular relationship. if (MarkThree.Guardian.Relationship.IsChildObject(childRow, parentRow)) { Invoke(new MessageDelegate(ShowMessage), Properties.Resources.CircularReferenceError, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } catch (Exception exception) { // Write the error and stack trace out to the debug listener EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace); } finally { // Release table locks. if (ClientMarketData.ObjectLock.IsReaderLockHeld) { ClientMarketData.ObjectLock.ReleaseReaderLock(); } if (ClientMarketData.ObjectTreeLock.IsReaderLockHeld) { ClientMarketData.ObjectTreeLock.ReleaseReaderLock(); } System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); } // Any commands created below will be constructed in this object and sent to the server for execution. bool isBatchValid = true; Batch batch = new Batch(); // If we made it here, the drag-and-drop is interpreted as a command to move a child from one parent to another. try { // Lock the tables needed for this operation. System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.ObjectTreeLock.AcquireReaderLock(CommonTimeout.LockWait); // Extract the primary identifiers from the user interface nodes. // This is the object that is being dragged. Find the row ClientMarketData.ObjectRow childRow = ClientMarketData.Object.FindByObjectId(childObject.ObjectId); if (childRow == null) { throw new Exception("This object has been deleted"); } // Find the object in the data model and make sure it still exists. ClientMarketData.ObjectTreeRow objectTreeRow = null; foreach (ClientMarketData.ObjectTreeRow innerObjectTreeRow in childRow.GetObjectTreeRowsByObjectObjectTreeChildId()) { if (innerObjectTreeRow.ParentId == fromObject.ObjectId) { objectTreeRow = innerObjectTreeRow; } } if (objectTreeRow == null) { throw new Exception("This relationship has been deleted by someone else."); } // Moving a child object from one parent to another must be accomplished as a transaction. Otherwise, an // orhpan object will be created if the operation fails midway through. TransactionPlan transaction = batch.Transactions.Add(); AssemblyPlan assembly = batch.Assemblies.Add("Core Service"); TypePlan type = assembly.Types.Add("MarkThree.Guardian.Core.ObjectTree"); // Construct a command delete the old parent relation. MethodPlan deleteObjectTree = transaction.Methods.Add(type, "Update"); deleteObjectTree.Parameters.Add(new InputParameter("objectTreeId", objectTreeRow.ObjectTreeId)); deleteObjectTree.Parameters.Add(new InputParameter("parentId", toObject.ObjectId)); deleteObjectTree.Parameters.Add(new InputParameter("childId", childObject.ObjectId)); deleteObjectTree.Parameters.Add(new InputParameter("rowVersion", objectTreeRow.RowVersion)); } catch (Exception exception) { // Write the error and stack trace out to the debug listener EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace); // This indicates that the batch shouldn't be executed. isBatchValid = false; } finally { // Release table locks. if (ClientMarketData.ObjectLock.IsReaderLockHeld) { ClientMarketData.ObjectLock.ReleaseReaderLock(); } if (ClientMarketData.ObjectTreeLock.IsReaderLockHeld) { ClientMarketData.ObjectTreeLock.ReleaseReaderLock(); } System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); } // If the command batch was built successfully, then execute it. if (isBatchValid) { try { // Call the web server to rename the object on the database. Note that this method must be called when there are // no locks to prevent deadlocking. That is why it appears in it's own 'try/catch' block. ClientMarketData.Execute(batch); } catch (BatchException batchException) { // Display each error in the batch. foreach (Exception exception in batchException.Exceptions) { MessageBox.Show(exception.Message, "Guardian Error"); } } } }
/// <summary> /// Rename the object. /// </summary> /// <param name="parameters">The object to be renamed.</param> private void RenameObject(object parameter) { // Extract the thread arguments object[] parameters = (object[])parameter; TreeNode treeNode = (TreeNode)parameters[0]; string name = (string)parameters[1]; // Extract the object that is associated with the TreeView node. MarkThree.Guardian.Object commonObject = (MarkThree.Guardian.Object)treeNode.Tag; // This command batch is constructed below and sent to the server for execution. Note that the batch is designed to // live beyond the block of code that locks the data model. This is to prevent the data model from being locked while // a relatively long server database operation is underway. bool isBatchValid = true; Batch batch = new Batch(); try { // Lock the table System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait); // Find the object in the data model and make sure it still exists. ClientMarketData.ObjectRow objectRow = ClientMarketData.Object.FindByObjectId(commonObject.ObjectId); if (objectRow == null) { throw new Exception("This object has been deleted."); } // Construct a command to rename the object. AssemblyPlan assembly = batch.Assemblies.Add("Core Service"); TypePlan type = assembly.Types.Add("MarkThree.Guardian.Core.Object"); TransactionPlan transaction = batch.Transactions.Add(); MethodPlan method = transaction.Methods.Add(type, "Update"); method.Parameters.Add(new InputParameter("rowVersion", objectRow.RowVersion)); method.Parameters.Add(new InputParameter("objectId", objectRow.ObjectId)); method.Parameters.Add(new InputParameter("name", name)); } catch (Exception exception) { // This serves as an indication that the batch couldn't be constructed. isBatchValid = false; // Write the error and stack trace out to the debug listener EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace); } finally { // Release table locks. if (ClientMarketData.ObjectLock.IsReaderLockHeld) { ClientMarketData.ObjectLock.ReleaseReaderLock(); } System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); } // If the command batch was built successfully, then execute it. If any part of it should fail, cancel the edit and // display the server errors. if (isBatchValid) { try { // Call the web server to rename the object on the database. Note that this method must be called when there // are no locks to prevent deadlocking. That is why it appears in it's own 'try/catch' block. ClientMarketData.Execute(batch); } catch (BatchException batchException) { // Display each error in the batch. foreach (Exception exception in batchException.Exceptions) { Invoke(new MessageDelegate(ShowMessage), exception.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } }
/// <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); } }
/// <summary> /// Read, parse and load the stylesheet into the middle tier. /// </summary> public void Load() { // If this flag is set during the processing of the file, the program will exit with an error code. this.HasErrors = false; // If the user wants to specify a new URL and certificate, then prompt for the connection info the next time a // WebTransactionProtocol sends off a batch. if (this.ForceLogin) { WebTransactionProtocol.IsUrlPrompted = true; WebTransactionProtocol.IsCredentialPrompted = true; } // Load up an XML document with the contents of the file specified on the command line. XmlDocument stylesheet = new XmlDocument(); stylesheet.Load(this.FileName); // The XML document has several nodes that need to be read -- and then removed -- that contain attributes of the // stylesheet. These nodes can be found easily using the XSL Path functions which need a namespace manager to sort out // the tag prefixes. XmlNamespaceManager namespaceManager = new XmlNamespaceManager(stylesheet.NameTable); namespaceManager.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform"); namespaceManager.AddNamespace("mts", "urn:schemas-markthreesoftware-com:stylesheet"); // The spreadhseet source has several nodes which contain information about how the data in the XML document should be // loaded into the server, such as the stylesheet identifier, the name and the stylesheet style. They are found at // this node. After these information nodes have been read, they are removed from the stylesheet source. XmlNode stylesheetNode = stylesheet.SelectSingleNode("xsl:stylesheet", namespaceManager); if (stylesheetNode == null) { throw new Exception("Syntax Error: missing stylesheet declaration."); } // Find the StylesheetId node. XmlNode StylesheetIdNode = stylesheetNode.SelectSingleNode("mts:stylesheetId", namespaceManager); if (StylesheetIdNode == null) { throw new Exception("Syntax Error: missing StylesheetId declaration."); } // Find the StylesheetStyle node. XmlNode stylesheetTypeCodeNode = stylesheetNode.SelectSingleNode("mts:stylesheetTypeCode", namespaceManager); if (stylesheetTypeCodeNode == null) { throw new Exception("Syntax Error: missing StylesheetStyle declaration."); } // Find the name node. XmlNode nameNode = stylesheetNode.SelectSingleNode("mts:name", namespaceManager); if (nameNode == null) { throw new Exception("Syntax Error: missing name declaration."); } // Extract the data from the XML nodes. this.StylesheetId = StylesheetIdNode.InnerText; this.StylesheetTypeCode = stylesheetTypeCodeNode.InnerText; this.StylesheetName = nameNode.InnerText; // Remove the stylesheet nodes from the XSL spreadsheet before loading it into the server. stylesheetNode.RemoveChild(StylesheetIdNode); stylesheetNode.RemoveChild(stylesheetTypeCodeNode); stylesheetNode.RemoveChild(nameNode); // Create a command to load the stylesheet from the data loaded from the file. Batch batch = new Batch(); TransactionPlan transaction = batch.Transactions.Add(); AssemblyPlan assembly = batch.Assemblies.Add(this.Assembly); TypePlan type = assembly.Types.Add(this.Type); MethodPlan method = transaction.Methods.Add(type, this.Method); method.Parameters.Add(new InputParameter("stylesheetId", this.StylesheetId)); method.Parameters.Add(new InputParameter("stylesheetTypeCode", this.StylesheetTypeCode)); method.Parameters.Add(new InputParameter("name", this.StylesheetName)); method.Parameters.Add(new InputParameter("text", stylesheet.InnerXml)); try { // Create a new web client that will serve as the connection point to the server and call the web services to execute // the command batch. WebTransactionProtocol.Execute(batch); } catch (BatchException) { foreach (MethodPlan batchMethod in transaction.Methods) { foreach (Exception exception in batchMethod.Exceptions) { Console.WriteLine(String.Format("{0}: {1}", method.Parameters["StylesheetId"].Value, exception.Message)); } } this.HasErrors = true; } }
/// <summary> /// Marshals the data needed refuse a chance to negotiate a trade. /// </summary> /// <param name="parameter">The thread initialization data.</param> private void DeclineNegotiationThread(object parameter) { // Extract the thread parameters int matchId = (int)parameter; // This batch, if succesfully constructed, will be sent to the server to deline the negotiation. Batch batch = new Batch(); try { // Lock the tables. System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); ClientMarketData.MatchLock.AcquireReaderLock(ClientTimeout.LockWait); ClientMarketData.OrderTypeLock.AcquireReaderLock(ClientTimeout.LockWait); ClientMarketData.SecurityLock.AcquireReaderLock(ClientTimeout.LockWait); ClientMarketData.WorkingOrderLock.AcquireReaderLock(ClientTimeout.LockWait); // Find the Match record. ClientMarketData.MatchRow matchRow = ClientMarketData.Match.FindByMatchId(matchId); // Construct a command decline the negotiation. AssemblyPlan assembly = batch.Assemblies.Add("Core Service"); TypePlan type = assembly.Types.Add("MarkThree.Guardian.Core.Negotiation"); TransactionPlan transaction = batch.Transactions.Add(); MethodPlan method = transaction.Methods.Add(type, "Insert"); method.Parameters.Add(new InputParameter("matchId", matchId)); method.Parameters.Add(new InputParameter("quantity", 0.0m)); method.Parameters.Add(new InputParameter("statusCode", Status.Declined)); } catch (Exception exception) { // Write the error and stack trace out to the debug listener EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace); // This indicates that the batch shouldn't be executed. batch = null; } finally { // Release the locks. if (ClientMarketData.MatchLock.IsReaderLockHeld) { ClientMarketData.MatchLock.ReleaseReaderLock(); } if (ClientMarketData.OrderTypeLock.IsReaderLockHeld) { ClientMarketData.OrderTypeLock.ReleaseReaderLock(); } if (ClientMarketData.SecurityLock.IsReaderLockHeld) { ClientMarketData.SecurityLock.ReleaseReaderLock(); } if (ClientMarketData.WorkingOrderLock.IsReaderLockHeld) { ClientMarketData.WorkingOrderLock.ReleaseReaderLock(); } System.Diagnostics.Debug.Assert(!ClientMarketData.IsLocked); } // If the command batch was built successfully, then execute it. if (batch != null) { try { // Call the web server to rename the object on the database. Note that this method must be called when there // are no locks to prevent deadlocking. That is why it appears in it's own 'try/catch' block. ClientMarketData.Execute(batch); } catch (BatchException batchException) { // Write any server generated error messages to the event log. foreach (Exception exception in batchException.Exceptions) { EventLog.Error("{0}, {1}", exception.Message, exception.StackTrace); } } } }