Execute vs ExecuteMultipleRequest vs ExecuteTransactionRequest
In day to day life a Dynamics CRM Developer write the code to perform transaction with CRM. So thought to write a blog which can describe how can we perform transaction without simple Create, Update, Delete, Associate, Dissociate organization messages.
1) Execute
Most of the CRM developer use Execute request for any CRM transaction request to CRM if they don’t want to use the methods(Create,Update, Delete etc..) in the IOrganizationService to perform common operations. We use (request and response classes) with the Execute method to do any transaction with CRM. The Execute method takes a message request class as a parameter and returns a message response class.
Simple example is as below:
Entity acc = new Entity("account");
acc["name"] = "Test Account";
CreateRequest req = new CreateRequest();
req.Target = acc;
CreateResponse response = (CreateResponse)service.Execute(req);
2) ExecuteMultipleRequest
Certain time in MS dynamic coder has bulk data to process in CRM. There we can use the ExecuteMultipleRequest message to support higher throughput bulk message passing scenarios in Microsoft Dynamics (online & on-premises), particularly in the case of Microsoft Dynamics 365 (online) where Internet latency can be the largest limiting factor. ExecuteMultipleRequest accepts an input collection of message Requests. The Request object can accommodate any type of CRM request for example SetStateRequest, UpsertRequest, CreateRequest at one shot together. ExecuteMultipleRequest is executed by using the IOrganizationService.Execute method.
For example, we can use ExecuteMultipleRequest when we do CRM integration with other system and CRM is the Target system to get bulk data feed from other system to process.
void UpsertAcc(Account[] accObj, IOrganizationService service)
{
ExecuteMultipleRequest multipleReq = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
// if ContinueOnError is true then it will allow to do request even there is some error in Operation
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
Entity accEntity;
foreach (var objRes in accObj)
{
// Use alternate key to update account
accEntity = new Entity("account", "accountnumber", objRes.accountnumber);
accEntity["new_balance"] = objRes.balance;
UpsertRequest req = UpsertRequest(accEntity);
multipleReq.Requests.Add(req);
}
service.Execute(multipleReq);
}
Note:
A) We can use ExecuteMultiple to improve performance for bulk data load
B) ContinueOnError property: When true, continue processing the next request in the collection even if a fault has been returned from processing the current request in the collection. When false, do not continue processing the next request.
C) ReturnResponses property: When true, return responses from each message request processed. When false, do not return responses.
D) Run-time limitations:
D.1) A limit of 1000 requests is typical though this maximum amount can be set for the Microsoft Dynamics 365 deployment. However I have analyzed sometime for complex request it fails for 600 request also. So better always send less than 500 records in one Execute Multiple request.
D.2) Throttling of concurrent calls – for Microsoft Dynamics 365 (online) there is a limit of 2 concurrent ExecuteMultipleRequest executions per organization. If that limit is exceeded, a “Server Busy” fault is thrown before the first request is ever executed. For an on-premises deployment, throttling is not enabled by default. For any Dynamics 365 deployment, a deployment administrator can set or change the throttling limit.
3) ExecuteTransactionRequest
Microsoft Dynamics 365 (online & on-premises) support batching of requests into a single web service method call. Each request in the batch is executed as part of a single database transaction. Failure of any request to complete successfully causes a rollback of any completed requests and no further processing is performed on requests not yet executed.
This is similar to ExecuteMultipleRequest however ExecuteTransactionRequest adds transaction support. In case of failure of one of the requests, all the previous requests will be rolled back. It’s something like we have in plugin written on In-Transaction.
Certain time we have object suppose we are copying or cloning data of a Parent entity and this parent entity have multiple different Entity object. { For example: Quote is Parent entity and Opportunity, account, Contacts, etc. are the child entities records of Quote record.}
Suppose we have one requirement to clone Quote and its child entity in one shot. Even if one child record creation is getting failure you want to rollback full transaction because you don’t want to create half or incorrect clone of the Quote. So here you can use ExecuteTransactionRequest.
// Create first Quote Parent record
OrganizationRequest req1 = new OrganizationRequest();
req1.RequestName = "Create";
req1.Parameters.Add("Target", new Quote() { Name = "Quote 1 " });
// Create Account Child record
OrganizationRequest req2 = new OrganizationRequest();
req2.RequestName = "Create";
req2.Parameters.Add("Target", new Account() { Name = "Acc 1 " });
// Create Opportunity Child Record
OrganizationRequest req3 = new OrganizationRequest();
req3.RequestName = "Create";
// CRM does not accept very old dates, hence exception is expected
req3.Parameters.Add("Target", new Opportunity() { Name = "Opp 1", OverriddenCreatedOn = new DateTime(100, 09, 09) });
// Using Transaction
ExecuteTransactionRequest transactionReq = new ExecuteTransactionRequest();
transactionReq.Requests = new OrganizationRequestCollection();
transactionReq.Requests.Add(req1);
transactionReq.Requests.Add(req2);
ExecuteTransactionResponse response = (ExecuteTransactionResponse)service.Execute(transactionReq);
// Result: As the second request fails, it would delete the first Account to rollback to earlier state.
1 ) ExecuteTransactionRequest cannot contain either "ExecuteTransactionRequest" or "ExecuteMultipleRequest" messages in Organzation request.
2) Its recommended to not use "ExecuteTransactionRequest" or ‘ExecuteMultipleRequest’ in Plug-ins or Action which is calling Workflow Dll.
3) Operations included in a batch request are executed sequentially and aren’t done in parallel.
4) "ExecuteTransactionRequest" may potentially block the database for the duration of the long-running transaction, so use it judiciously.
5) "ExecuteTransactionRequest" feature came in Dynamics CRM 2016 8.0 version. So this message can not be used for earlier version of Dynamics CRM.
Symptoms of using batch requests
Due to their long-running nature, using ExecuteMultipleRequest or ExecuteTransactionRequest message request classes within the context of a plug-in or workflow activity expose sandbox-isolated plug-in types to the two-minute (120000ms) channel timeout exception and can degrade the user experience for synchronous registrations.
Guidance
Use these batch messages where code is being executed outside of the platform execution pipeline, such as integration scenarios where network latency would likely reduce the throughput and increase the duration of larger, bulk operations.
More specifically, use them in the following scenarios:
Use ExecuteMultipleRequest to bulk load data or external processes that are intentional about executing long-running operations (greater than two minutes).
Use ExecuteMultipleRequest to minimize the round trips between custom client and Dynamics 365 servers, thereby reducing the cumulative latency incurred.
Use ExecuteTransactionRequest for external clients that require the batch of operations to be committed as a single, atomic database transaction or rollback if an exception is encountered. Be aware of the potential for database blocking for the duration of the long-running transaction.
No comments:
Post a Comment