Executing Messages in a Single Transaction in Dynamics CRM 2015

Ahmed Anwar, 07 August 2015

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 ExecuteTransactionRequest class:

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 = new Entity("salesorder");

order["name"] = "Shipment Order: A Song of Ice and Fire";

       

Entity invoice = new Entity("invoice");

invoice["name"] = "Invoice: INV-00001";

       

Entity email = new Entity("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 = new CreateRequest

{

Target = order

};

CreateRequest createInvoiceRequest = new CreateRequest

{

Target = invoice

};

CreateRequest createEmailRequest = new CreateRequest

{

Target = email

};

3. Instantiate the
ExecuteTransactionRequest object 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 = new ExecuteTransactionRequest

{

// Pass independent operations

Requests = new OrganizationRequestCollection

{

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.



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

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.