Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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.
** 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);
}
}
}
}
}
}
** 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();
}
}
}
}
}
}
}