Откат транзакции в плагине без отката данных
Некоторое время назад MS ввела в CRM транзакционную составляющую в работу конвейера работы плагинов. Почти во всех смыслах это хороший функционал – как минимум сохраняется целостность данных. Но иногда требуется выполнить какую-либо работу, которую не нужно откатывать. Например, писать сообщения в кастомный лог, представляющий собой кастомный объект в CRM. Или просто выдать сообщение пользователю из плагина (в эксепшене), но и выполнить полезную работу. При возникновении такой ошибки в конвейере все созданные или обновленные данные будут тут же удалены.
Есть несколько способов решить эту проблему, включая создание новой организационной службы в Вашем плагине, но это требует, чтобы Вы хранили где-нибудь URL сервера. Еще один способ: создание стороннего веб-сервиса и вызов его из плагина, что также доставляет немало хлопот.
Но есть способ обойти откат и внутри самого плагина, используя стандартные методы, а именно функцию ExecuteMultiple CRM. Фокус заключается в том, что ее вызов работает в ее собственной транзакции и не откатывается при эксепшене в родительской транзакции.
Примерно так:
using System; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Messages; namespace exception { public class exceptionClass : IPlugin { public void Execute(IServiceProvider serviceProvider) { IPluginExecutionContext pluginExecutionContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService orgService = serviceFactory.CreateOrganizationService(pluginExecutionContext.UserId); try { var z = 0; var x = 1 / z; } catch (Exception ex) { Entity acc = new Entity("account"); acc["name"] = "Test1"; acc["description"] = ex.Message; ExecuteMultipleRequest multipleRequest = new ExecuteMultipleRequest() { Requests = new OrganizationRequestCollection(), Settings = new ExecuteMultipleSettings() { ContinueOnError = true, ReturnResponses = false } }; CreateRequest request = new CreateRequest() { Target = acc }; multipleRequest.Requests.Add(request); orgService.Execute(multipleRequest); throw; } } } }
Также учтите, что в свойствах ExecuteMultipleRequest надо обязательно установить ContinueOnError = true.
Жаль я эту статью не прочел месяц назад 🙂