In CRM 2015, you can now execute multiple CRM requests in a single transaction. This gives developers the ability to easily rollback or cancel transactions if one of the CRM requests within the transaction fail.
For example, imagine you have a website which allows customers to buy products. Each purchase creates an Order and Invoice in CRM, and also sends an e-mail confirmation to the customer with their order number (in that sequence). Previously, if the Invoice failed to create, you would have to implement your own rollback procedure by deleting the Order record that got created before it.
We can now use the ExecuteTransactionRequest message which will automatically rollback the entire transaction if any of the associated requests fail.
Notice the definition of ExecuteTransactionRequestclass:
Image may be NSFW.
Clik here to view.
The Requests property takes any request message which inherits from OrganizationRequest. This means that simple operations (such as create, update, retrieve, and delete) and complex operations (such as custom actions) can be included in a transaction.
Note: According to the documentation, there is no limit for adding requests to a single transaction.
If you want to process Responses coming from CRM like Create or Retrieve, set ReturnResponses to True.
The following code snippets show how multiple CRM requests can be added to a transaction.
1. Instantiate the records.
Entity order = newEntity("salesorder");
order["name"] = "Shipment Order: A Song of Ice and Fire";
Entity invoice = newEntity("invoice");
invoice["name"] = "Invoice: INV-00001";
Entity email = newEntity("email");
email["subject"] = "Thank you for purchasing: A Song of Ice and Fire";
2. Pass the objects to the Target of each request
CreateRequest createOrderRequest = newCreateRequest
{
Target = order
};
CreateRequest createInvoiceRequest = newCreateRequest
{
Target = invoice
};
CreateRequest createEmailRequest = newCreateRequest
{
Target = email
};
3. Instantiate the ExecuteTransactionRequestobject and pass each request. Note that the transaction will execute the requests in the order that they are added. Also note that I have created a plugin which will force the Invoice to fail during creation, so we can see what happens with the entire transaction.
ExecuteTransactionRequest transactionRequest = newExecuteTransactionRequest
{
// Pass independent operations
Requests = newOrganizationRequestCollection
{
createOrderRequest,
createInvoiceRequest, // we have forced this request to fail
createEmailRequest
},
};
4. Pass the request to the Execute method.
try
{
ExecuteTransactionResponse transactResponse =
(ExecuteTransactionResponse)_service.Execute(transactionRequest);
// Display the results returned in the responses
foreach (var response in transactResponse.Responses)
{
foreach (var result in response.Results)
{
Console.WriteLine(
"{0} {1} {2}", response.ResponseName, result.Key, result.Value);
}
}
}
catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
{
Console.WriteLine("Transaction rolled back because: {0}", ex.Message);
}
catch (Exception)
{
throw;
}
5. The exception thrown from the Invoice plugin is caught and the entire transaction is rolled back.
Image may be NSFW.
Clik here to view.
6. Here is the result if we allow the creation of the Invoice. Notice that the response has returned the name of each operation and the ID of each request
Image may be NSFW.
Clik here to view.
The use of transactions will greatly simplify the way that you build integrations with your CRM implementation. Developers don't need to worry about rolling back specific operations if something fails.
Image may be NSFW.Clik here to view.