Compartilhar via


Concurrency

When update operations are performed, the Dynamics GP service must handle any concurrency issues that occur. These issues happen because other users have locked the same rows in the database that the update operation is trying to change. Documents for which the Microsoft Dynamics GP client application actively locks rows, such as sales document, can produce these situations.

Typically, other users in Microsoft Dynamics GP won't see concurrency issues caused by Dynamics GP service operations. The update operations occur quickly, and hold row locks for only the time necessary to perform the update. If a concurrency issue is caused by a Dynamics GP service update operation, the other user affected will see the standard message displayed that indicates another user has updated a record.

The most likely scenario in which a Dynamics GP service update operations will encounter concurrency issues occurs when the web service application is updating a large number of rows that the Microsoft Dynamics GP client can actively lock. For example, if a web service application was updating all of the sales orders created on a specific date, and other users are accessing the Microsoft Dynamics GP system, it is possible the web service application will encounter one of the sales documents being locked (in use). If this occurs, a validation exception will occur, indicating the sales order being updated was in use.

Your code must be able to handle concurrency exceptions that occur. The following C# example demonstrates one way this can be done. This example updates the comment for all sales orders created on 3/17/10. If a concurrency exception occurs because a sales order is being edited by another user, the following message is displayed. The user can choose to try updating the sales order again, or canceling the update and moving to the next document.

In this example, a list of the sales orders for the specific date is retrieved. The comment for each of these order is updated. Note the try...catch block that handles the validation error if a concurrency issue occurs. If the user chooses to retry the update operation, the goto statement causes the update operation to be run again.

Cc508742.LegacyEndpoint(en-us,MSDN.10).gif** Legacy endpoint**

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using DynamicsGPWebServiceSample.DynamicsGPService;
using System.Xml;
using System.Web.Services.Protocols;

namespace DynamicsGPWebServiceSample
{
    class Program
    {
        static void Main(string[] args)
        {
            CompanyKey companyKey;
            Context context;
            BetweenRestrictionOfNullableOfDateTime
            transactionDateRestriction;
            SalesOrderCriteria salesOrderCriteria;
            SalesOrderSummary[] salesOrderSummary;
            DateTime dateValue;
            SalesDocumentKey salesOrderKey;
            SalesOrder salesOrder;
            Policy salesOrderUpdatePolicy;
            ValidationResult validationResult;

            // Create an instance of the service
            DynamicsGP wsDynamicsGP = new DynamicsGP();

            // Be sure the default credentials are used
            wsDynamicsGP.UseDefaultCredentials = true;

            // Create a context with which to call the service
            context = new Context();

            // Specify which company to use (sample company)
            companyKey = new CompanyKey();
            companyKey.Id = (-1);

            // Set up the context object
            context.OrganizationKey = (OrganizationKey)companyKey;

            // Create a date restriction object
            transactionDateRestriction = new
            BetweenRestrictionOfNullableOfDateTime();
            dateValue = new DateTime(2010, 3, 17);
            transactionDateRestriction.EqualValue = dateValue;

            // Create a sales order criteria object
            salesOrderCriteria = new SalesOrderCriteria();
            salesOrderCriteria.Date = transactionDateRestriction;

            // Retrieve the sales order summaries specified by the criteria
            salesOrderSummary = wsDynamicsGP.GetSalesOrderList(
            salesOrderCriteria, context);

            // Retrieve the update policy for sales orders
            salesOrderUpdatePolicy = wsDynamicsGP.GetPolicyByOperation(
            "UpdateSalesOrder", context);

            // Update the comment for each of the documents found
            foreach (SalesOrderSummary a in salesOrderSummary)
            {
                // Create a sales document key
                salesOrderKey = new SalesDocumentKey();
                salesOrderKey = a.Key;

                // Retrieve the sales order
                salesOrder = wsDynamicsGP.GetSalesOrderByKey(salesOrderKey,
                context);

                // Set the comment property
                salesOrder.Comment = "Customer notified - March 17";

                // Update the sales order object
                UpdateSalesDocument:
                try
                {
                    wsDynamicsGP.UpdateSalesOrder(salesOrder, context,
                    salesOrderUpdatePolicy);
                }
                catch (SoapException soapErr)
                {
                    // Try retrieving the Message node
                    XmlDocument doc = new XmlDocument();
                    XmlNamespaceManager nsManager = new
                        XmlNamespaceManager(doc.NameTable);
                    nsManager.AddNamespace("sm",
            "http://schemas.datacontract.org/2004/07/System.ServiceModel");
                    doc.LoadXml(soapErr.Detail.InnerXml);
                    XmlNode node = doc.SelectSingleNode(
                        "//sm:InnerException//sm:Message", nsManager);
                    if (node != null)
                    {
                        // Use the GUID to load the validation details
                        Guid LogId = new Guid(node.InnerText.Trim());

                        // Get the validation result object
                        validationResult = wsDynamicsGP.
                        GetLoggedValidationResultByKey(LogId, context);

                        if (validationResult.Errors[0].Id ==
                        "EConnectError-2079")
                        {
                            // It is a concurrency error, with record in use
                            if (MessageBox.Show(null,
                            "Document: " + a.Key.Id + ".  " +
                            validationResult.Errors[0].Message + ".",
                            "Sales Document Update",
                            MessageBoxButtons.RetryCancel,
                            MessageBoxIcon.Warning,
                            MessageBoxDefaultButton.Button1) ==
                            DialogResult.Retry)
                            {
                                goto UpdateSalesDocument;
                            }
                        }
                        else
                        {
                            // It is a different error
                            MessageBox.Show(null,
                            validationResult.Errors[0].Message,
                            "Sales Document Update");
                        }
                    }
                    else
                    {
                        // Display the system exception message
                        MessageBox.Show(soapErr.Message, "Sample",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    }
                }
            }
        }
    }
}

Cc508742.NativeEndpoint(en-us,MSDN.10).gif** Native endpoint **

using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WebServiceSample.DynamicsGPService;

using System.ServiceModel;

namespace DynamicsGPWebServiceSample
{
    class Program
    {
        static void Main(string[] args)
        {
            CompanyKey companyKey;
            Context context;
            BetweenRestrictionOfNullableOfdateTime
                transactionDateRestriction;
            SalesOrderCriteria salesOrderCriteria;
            SalesOrderSummary[] salesOrderSummary;
            DateTime dateValue;
            SalesDocumentKey salesOrderKey;
            SalesOrder salesOrder;
            Policy salesOrderUpdatePolicy;
            ValidationResult validationResult;

            // Create an instance of the service
            DynamicsGPClient wsDynamicsGP = new DynamicsGPClient();

            // Create a context with which to call the service
            context = new Context();

            // Specify which company to use (sample company)
            companyKey = new CompanyKey();
            companyKey.Id = (-1);

            // Set up the context object
            context.OrganizationKey = (OrganizationKey)companyKey;

            // Create a date restriction object
            transactionDateRestriction = new
                BetweenRestrictionOfNullableOfdateTime();
            dateValue = new DateTime(2010, 3, 19);
            transactionDateRestriction.EqualValue = dateValue;

            // Create a sales order criteria object
            salesOrderCriteria = new SalesOrderCriteria();
            salesOrderCriteria.Date = transactionDateRestriction;

            // Retrieve the sales order summaries specified by the criteria
            salesOrderSummary = wsDynamicsGP.GetSalesOrderList(
            salesOrderCriteria, context);

            // Retrieve the update policy for sales orders
            salesOrderUpdatePolicy = wsDynamicsGP.GetPolicyByOperation(
            "UpdateSalesOrder", context);

            // Update the comment for each of the documents found
            foreach (SalesOrderSummary a in salesOrderSummary)
            {
                // Create a sales document key
                salesOrderKey = new SalesDocumentKey();
                salesOrderKey = a.Key;

                // Retrieve the sales order
                salesOrder = wsDynamicsGP.GetSalesOrderByKey(salesOrderKey,
                context);

                // Set the comment property
                salesOrder.Comment = "Customer notified - March 17";

                // Update the sales order object
                UpdateSalesDocument:
                try
                {
                    wsDynamicsGP.UpdateSalesOrder(salesOrder, context,
                    salesOrderUpdatePolicy);

                    // Close the service
                    if (wsDynamicsGP.State != CommunicationState.Faulted)
                    {
                        wsDynamicsGP.Close();
                    }
                }
                catch (FaultException<System.ServiceModel.ExceptionDetail> ex)
                {
                    if (ex.Detail.InnerException != null)
                    {
                        // Use the GUID to load the validation details
                        Guid LogId = new Guid(
                            ex.Detail.InnerException.Message.Trim());

                        // Get the validation result object
                        validationResult = wsDynamicsGP.
                            GetLoggedValidationResultByKey(LogId, context);

                        if (validationResult.Errors[0].Id ==
                        "EConnectError-2079")
                        {
                            // It is a concurrency error, with record in use
                            if (MessageBox.Show(null,
                            "Document: " + a.Key.Id + ".  " +
                            validationResult.Errors[0].Message + ".",
                            "Sales Document Update",
                            MessageBoxButtons.RetryCancel,
                            MessageBoxIcon.Warning,
                            MessageBoxDefaultButton.Button1) ==
                            DialogResult.Retry)
                            {
                                goto UpdateSalesDocument;
                            }
                            else
                            {
                                if (wsDynamicsGP.State !=                                                                    CommunicationState.Faulted)
                                {
                                    wsDynamicsGP.Close();
                                }
                            }
                        }
                        else
                        {
                            // It is a different error
                            MessageBox.Show(null,
                            validationResult.Errors[0].Message,
                            "Sales Document Update");
                        }
                    }
                    else
                    {
                        // Display the system exception message
                        MessageBox.Show(ex.Message, "Sample",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop);

                        if (wsDynamicsGP.State != CommunicationState.Faulted)
                        {
                            wsDynamicsGP.Close();
                        }
                    }
                }
            }
        }
    }
}