Есть ли способ отследить \ войти в sql с помощью Dapper?

Есть ли способ вывести сгенерированный sql в журнал отладки или что-то? Я использую его в решении winforms, поэтому идея мини-профилирования не будет работать для меня.

4 ответа

Решение

Я получил ту же проблему и реализовал некоторый код после выполнения некоторого поиска, но не имея готового к использованию материала. Есть пакет на nuget MiniProfiler.Интеграции, которыми я хотел бы поделиться.

Обновление V2: поддерживает работу с другими серверами баз данных, для MySQL требуется https://www.nuget.org/packages/MiniProfiler.Integrations.MySql/

Ниже приведены шаги для работы с SQL Server:

1. Установить соединение

var factory = new SqlServerDbConnectionFactory(_connectionString);
using (var connection = DbConnectionFactoryHelper.New(factory, CustomDbProfiler.Current))
{
 // your code
}

2.После того, как все выполнено, запишите все команды в файл, если хотите

File.WriteAllText("SqlScripts.txt", CustomDbProfiler.Current.ProfilerContext.BuildCommands());

У Даппера в настоящее время нет контрольно-измерительного пункта здесь. Возможно, это связано, как вы заметили, с тем фактом, что мы (как авторы) используем для этого мини-профилировщик. Однако, если это поможет, основные части мини-профилировщика на самом деле разработаны так, чтобы быть независимыми от архитектуры, и я знаю, что другие люди используют его с winforms, wpf, wcf и т. Д., Что даст вам доступ к оболочке соединения профилирования / трассировки,

Теоретически было бы вполне возможно добавить некоторую общую точку захвата, но меня волнуют две вещи:

  • (в первую очередь) безопасность: поскольку dapper не имеет понятия контекста, для злокачественного кода было бы действительно очень просто спокойно присоединить, чтобы прослушать весь sql-трафик, проходящий через dapper; Мне действительно не нравится, как это звучит (это не проблема с подходом "декоратор", так как вызывающая сторона владеет соединением, отсюда и контекст регистрации)
  • (вторичная) производительность: но... по правде говоря, трудно сказать, что это простая проверка делегата (которая, вероятно, будет null в большинстве случаев) будет иметь большое влияние

Конечно, вы могли бы сделать еще одну вещь: украсть код обертки соединения из мини-профилировщика и заменить контекстный профилировщик просто: Debug.WriteLine и т.п.

Вы можете использовать профилировщик SQL, расположенный в SQL Management Studio -> Extras -> SQL Server Profiler (расширения Dapper не требуются - могут работать с другими СУБД, если у них есть инструмент SQL Profiler).

Затем начните новый сеанс.

Вы получите что-то вроде этого, например (вы видите все параметры и полную строку SQL):

exec sp_executesql N'SELECT * FROM Updates WHERE CAST(Product_ID as VARCHAR(50)) = @appId AND (Blocked IS NULL OR Blocked = 0) AND (Beta IS NULL OR Beta = 0 OR @includeBeta = 1) AND (LangCode IS NULL ИЛИ LangCode IN (SELECT * FROM STRING_SPLIT(@langCode, '','')))',N'@appId nvarchar(4000),@includeBeta bit,@langCode nvarchar(4000)',@appId=N'fea5b0a7-1da6-4394-b8c8-05e7cb979161',@includeBeta=0,@langCode=N'de'

Ура

Попробуйте Dapper.Logging.

Вы можете получить его из NuGet. Это работает так: вы передаете свой код, который создает ваше фактическое соединение с базой данных, в фабрику, которая создает обернутые соединения. Каждый раз, когда обернутое соединение открывается или закрывается, или вы запускаете запрос к нему, оно будет зарегистрировано. Вы можете настроить шаблоны сообщений журнала и другие параметры, например, сохранять ли параметры SQL. Прошедшее время также сохраняется.

На мой взгляд, единственным недостатком является скудность документации, но я думаю, что это просто потому, что это новый проект (на момент написания этой статьи). Мне пришлось немного покопаться в репо, чтобы понять его и настроить его по своему вкусу, но теперь он отлично работает.

Из документации:

Инструмент состоит из простых декораторов для DbConnection иDbCommand которые отслеживают время выполнения и записывают сообщения вILogger<T>. В ILogger<T>может обрабатываться любой структурой журналирования (например, Serilog). Результат аналогичен поведению ведения журнала EF Core по умолчанию.

Библиотека объявляет вспомогательный метод для регистрацииIDbConnectionFactoryв контейнере IoC. Фабрика соединений не зависит от поставщика SQL. Вот почему вы должны указать настоящий заводской метод:

services.AddDbConnectionFactory(prv => new SqlConnection(conStr));

После регистрации IDbConnectionFactory можно внедрить в классы, которым требуется соединение SQL.

private readonly IDbConnectionFactory _connectionFactory;
public GetProductsHandler(IDbConnectionFactory connectionFactory)
{
    _connectionFactory = connectionFactory;
}

В IDbConnectionFactory.CreateConnection вернет оформленную версию, в которой регистрируется активность.

using (DbConnection db = _connectionFactory.CreateConnection())
{
    //...
}

Это не является исчерпывающим и, по сути, немного взломать, но если у вас есть sql и вы хотите инициализировать свои параметры, это полезно для базовой отладки.

public static class DapperExtensions
    {
        public static string ArgsAsSql(this DynamicParameters args)
        {
            var sb = new StringBuilder();
            foreach (var name in args.ParameterNames)
            {
                var pValue = args.Get<dynamic>(name);

                var type = pValue.GetType();

                if (type == typeof(DateTime))
                    sb.AppendFormat("DECLARE @{0} DATETIME ='{1}'\n", name, pValue.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                else if (type == typeof(bool))
                    sb.AppendFormat("DECLARE @{0} BIT = {1}\n", name, (bool)pValue ? 1 : 0);
                else if (type == typeof(int))
                    sb.AppendFormat("DECLARE @{0} INT = {1}\n", name, pValue);
                else if (type == typeof(List<int>))
                    sb.AppendFormat("-- REPLACE @{0} IN SQL: ({1})\n", name, string.Join(",", (List<int>)pValue));
                else
                    sb.AppendFormat("DECLARE @{0} NVARCHAR(MAX) = '{1}'\n", name, pValue.ToString());
            }

            return sb.ToString();
        }
    }

Затем вы можете просто использовать это в окнах непосредственного просмотра или просмотра, чтобы получить SQL.

Просто чтобы добавить обновление здесь, так как я вижу, что этот вопрос все еще получает довольно много хитов - в настоящее время я использую либо Glimpse, либо Stackify Prefix, оба из которых имеют возможности трассировки команд sql.

Это не совсем то, что я искал, когда я задал оригинальный вопрос, но решил ту же проблему.

Другие вопросы по тегам