Разработка
17
Май
0

Откат транзакции в плагине без отката данных

Некоторое время назад 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.



Комментарии (0)

*

code