Разработка
04
Июн
0

Получение SQL ConnectionString из плагина

Иногда в плагинах CRM необходимо выполнить прямой запрос к БД. Для этого Вам нужна строка подключения к CRM. Но нет никакого нормального поддерживаемого метода, предоставляемого SDK, чтобы ее получить. И тут у Вас есть несколько вариантов, где ее взять: захардкодить, передавать в параметрах или вовсе хранить в CRM. Но в некоторых случаях ее можно получить из контекста плагина. Этот код поможет Вам получать ConnectString из плагина, кастомного БП или Экшена:

using System;
using Microsoft.Xrm.Sdk;
using System.Data.SqlClient;
using System.Reflection;

namespace ConnectionString
{
    public class ConnectionString : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            var platformContext = context.GetType().InvokeMember("PlatformContext", BindingFlags.GetProperty, null, context, null);
            var transaction = (SqlTransaction)platformContext.GetType().InvokeMember("SqlTransaction", BindingFlags.GetProperty, null, platformContext, null);
            throw new InvalidPluginExecutionException(transaction.Connection.ConnectionString);
        }
    }
}

Данный маневр работает только для On-Premise и без режима Sandbox.


Примечание: если Вы попробуете из транзакционного конвейера выполнить SQL-запрос для того же объекта, который Вы обновляете/добавляете, то Вы получите блокировку, что в итоге приведет к таймауту.

Вы можете обойти это несколькими путями:

  • Выполнить SQL-запрос вне транзакции: на этапе PreValidation или в асинхронном плагине.
  • Обратится к процедуре, хранящейся на сторонней БД, которая в свою очередь выполнит запрос к базе CRM (возможно при этом Вы должны будете использовать SET TRUSTWORTHY ON, чтобы гарантировать, что передать контекст безопасности между этими двумя БД).
  • Воспользоваться транзакцией текущего плагина:
    IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    object platformContext = context.GetType().InvokeMember("PlatformContext", BindingFlags.GetProperty, null, context, null);
    SqlTransaction tx = (SqlTransaction)platformContext.GetType().InvokeMember("SqlTransaction", BindingFlags.GetProperty, null, platformContext, null);
    DataSet result = SqlHelper.ExecuteDataset(tx, CommandType.Text, "SELECT ...");
    
Комментарии (0)

*

code