Есть ли способ отследить \ войти в 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.
Это не совсем то, что я искал, когда я задал оригинальный вопрос, но решил ту же проблему.