Transaction aware batch processing using ‘ExecuteMultipleRequest’
In this article, I am going to discuss about transaction aware batch processing in ExecuteMultipleRequest using ExecuteTransactionRequest.
Is ‘ExecuteMultipleRequest’ not a transaction aware?
- By design, ‘ExecuteMultipleRequest’ is non-transactional.
- Which means ‘Request’ objects added to ‘ExecuteMultipleRequest’ are independent of each other and if any exception occurred in any of the ‘Request’ will not roll back previously committed ‘Requests’.
- However you have an option to stop the batch (i.e., By setting ContinueOnError = false), if any exception occurs.
- Important to note is that, this behavior is not a transaction aware and ‘Requests’ executed prior to the error, will still be committed.
How can we achieve ‘Transaction’ in Batch execution?
- Using ExecuteTransactionRequest, we can achieve ‘Transaction’ (i.e., Commit and Rollback) in Batch execution
- ExecuteTransactionRequest will execute the all the ‘Requests’ in a single transaction.
- If any exception occurred in any of the ‘Request’ execution, will roll back all the previously executed ‘Requests’.
Then why do we need ‘Transaction aware’ feature in ‘ExecuteMultipleRequest’?
- ‘ExecuteMultipleRequest’ has an option to either stop the operation or suppress the exception, if any exception occurs, using ContinueOnError property.
- However there is no option to achieve ‘Transactional Batch feature’ in ExecuteMultipleRequest.
Lets see how we get both features together in ‘ExecuteMultipleRequest’?
[Code snippet] ‘ExecuteMultipleRequest’ with ‘Transaction aware’ option
- ‘ExecuteMultipleRequest’ can have ‘ExecuteTransactionRequest’ object as a ‘Request’, and as we know ‘ExecuteTransactionRequest’ is transaction aware, it get executed in transaction.
var connectionString = ConfigurationManager.ConnectionStrings[“Xrm”].ConnectionString;
CrmServiceClient crmConn = new CrmServiceClient(connectionString);// Instantiate ExecuteMultiple
var reqExecMultiple = new ExecuteMultipleRequest(){
Requests = new OrganizationRequestCollection(),
Settings = new ExecuteMultipleSettings(){
ContinueOnError = false,
ReturnResponses = true
}
};// Instantiate ExecuteTransaction
var reqExecTransaction = new ExecuteTransactionRequest(){
Requests = new OrganizationRequestCollection()
};// Add 20 requests of type ‘CreateRequest’ to ‘Execute Transaction’
for (int indxStudent = 0; indxStudent < 20; indxStudent++){
// Instantiate ‘Student’ record
var entStudent = new Entity(“new_student”);
entStudent[“new_name”] = “Student : ” + indxStudent.ToString();// Instantiate ‘CreateRequest’
CreateRequest reqCreate = new CreateRequest{
Target = entStudent
};// Add ‘CreateRequest’ object to ‘ExecuteTransaction’ Requests collection
reqExecTransaction.Requests.Add(reqCreate);
}// Execute the ‘Execute Multiple Request’
using (_serviceProxy = crmConn.OrganizationServiceProxy){
_service = _serviceProxy;// Add ‘Execute Transaction’ request object to ‘ExecuteMulitple’ Requests collection
reqExecMultiple.Requests.Add(reqExecTransaction);// Execute Multiple Request
var response = (ExecuteMultipleResponse)_service.Execute(reqExecMultiple);// Read the GUID of created Students
foreach (var responseItem in response.Responses){
var execTransactionResponse = (ExecuteTransactionResponse)responseItem.Response;
foreach (var createResponse in execTransactionResponse.Responses){
Console.WriteLine(“Student created: {0}”, ((CreateResponse)createResponse).id);
}
}
}
Key Notes:
- ‘ExecuteTransactionRequest’ cannot contain either ‘ExecuteTransactionRequest’ or ‘ExecuteMultipleRequest’ messages.
- Its recommended to not use ‘ExecuteTransactionRequest’ or ‘ExecuteMultipleRequest’ in Plug-ins. Refer article.
- Operations included in a batch request are executed sequentially and aren’t done in parallel.
- ‘ExecuteTransactionRequest’ may potentially block the database for the duration of the long-running transaction, so use it judiciously.
🙂
Reblogged this on CRM Backlog.
Reblogged this on ECELLORS CRM Blog