有没有办法使用 Dapper 来跟踪\记录 sql?

问题描述 投票:0回答:6

有没有办法将生成的sql转储到调试日志或其他什么?我在 winforms 解决方案中使用它,因此迷你分析器的想法对我不起作用。

dapper
6个回答
37
投票

我遇到了同样的问题,并在进行一些搜索后实现了一些代码,但没有现成的东西。 nuget 上有一个包 MiniProfiler.Integrations 我想分享一下。

更新V2:支持与其他数据库服务器配合使用,对于MySQL需要有MiniProfiler.Integrations.MySql

以下是使用 SQL Server 的步骤:

1.实例化连接

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

2.完成所有工作后,如果需要,可以将所有命令写入文件

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

18
投票

Dapper 目前没有检测点。正如您所指出的,这可能是由于我们(作为作者)使用迷你分析器来处理这个问题。然而,如果有帮助的话,迷你分析器的核心部分实际上被设计为架构中立,而且我知道其他人将它与 winforms、wpf、wcf 等一起使用 - 这将使您能够访问分析/跟踪连接包装器.

理论上,添加一些全面捕获点是完全有可能的,但我担心两件事:

  • (主要)安全性:由于 dapper 没有上下文的概念,因此恶意代码很容易悄悄地附加到嗅探通过 dapper 的所有 sql 流量;我真的不喜欢这样的声音(这不是“装饰器”方法的问题,因为调用者拥有连接,因此拥有日志记录上下文) (次要)性能:但是......事实上,很难说简单的委托检查(在大多数情况下可能是
  • null
  • )会产生多大影响
    
    
    
  • 当然,您可以做的另一件事是:从迷你分析器中窃取连接包装器代码,并将分析器上下文内容替换为:
Debug.WriteLine

等。

    


9
投票
SQL Management Studio

→ Extras → SQL Server Profiler 菜单中的 SQL 探查器(无需 Dapper 扩展 - 当其他 RDBMS 也有 SQL 探查器工具时,可以与其他 RDBMS 一起使用)。 然后,开始新的会话。

您将得到类似这样的信息(您会看到所有参数和完整的 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 OR 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'



9
投票
Dapper.Logging

您可以从 NuGet 获取它。它的工作方式是将创建实际数据库连接的代码传递到创建包装连接的工厂中。每当打开或关闭包装连接或对其运行查询时,都会记录该连接。您可以配置日志消息模板和其他设置,例如是否保存 SQL 参数。经过的时间也会被保存。

在我看来,唯一的缺点是文档很少,但我认为这只是因为它是一个新项目(截至撰写本文时)。我必须深入研究一下该存储库才能理解它并根据我的喜好对其进行配置,但现在它工作得很好。

来自文档:

该工具由简单的装饰器组成
DbConnection

DbCommand
跟踪执行时间并将消息写入
ILogger<T>
ILogger<T>
可以由任何日志框架处理 (例如 Serilog)。结果类似于默认的 EF Core 日志记录 行为。
lib 声明了一个辅助方法来注册
IoC 容器中的 

IDbConnectionFactory

。连接工厂是 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())
{
    //...
}

    

6
投票

public static class DapperExtensions { public static string ArgsAsSql(this DynamicParameters args) { if (args is null) throw new ArgumentNullException(nameof(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。


3
投票
Glimpse

(似乎现在已经死了)或 Stackify Prefix 两者都具有 sql 命令跟踪功能。 这并不完全是我在问原来的问题时所寻找的,但解决了同样的问题。

© www.soinside.com 2019 - 2024. All rights reserved.