【发布时间】:2013-08-30 09:50:18
【问题描述】:
有没有办法将生成的 sql 转储到调试日志之类的?我在 winforms 解决方案中使用它,所以迷你分析器的想法对我不起作用。
【问题讨论】:
标签: dapper
有没有办法将生成的 sql 转储到调试日志之类的?我在 winforms 解决方案中使用它,所以迷你分析器的想法对我不起作用。
【问题讨论】:
标签: dapper
我遇到了同样的问题,并在进行了一些搜索后实现了一些代码,但没有现成的东西。 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.BuildCommands());
【讨论】:
CustomDbProfiler.Current.ProfilerContext 我不见了。
Dapper 目前在此处没有检测点。正如您所注意到的,这可能是由于我们(作为作者)使用迷你分析器来处理这个事实。但是,如果它有帮助,mini-profiler 的核心部分实际上被设计为与架构无关,而且我知道其他人将它与 winforms、wpf、wcf 等一起使用——这将使您可以访问分析/跟踪连接包装器.
理论上,添加一些全面的捕获点是完全可能的,但我担心两件事:
null)会产生很大的影响当然,您可以做的另一件事是:从 mini-profiler 中窃取连接包装代码,并将 profiler-context 的内容替换为:Debug.WriteLine 等。
【讨论】:
这并不详尽,本质上是一个小技巧,但如果你有你的 sql 并且你想初始化你的参数,它对于基本调试很有用。
public static class DapperExtensions
{
if (args is null) throw new ArgumentNullException(nameof(args));
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。
【讨论】:
您应该考虑使用位于 SQL Management Studio → Extras → SQL Server Profiler 菜单中的 SQL 分析器(不需要 Dapper 扩展 -当他们也有一个 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'
【讨论】:
您可以从 NuGet 获取它。它的工作方式是将创建实际数据库连接的代码传递给创建包装连接的工厂。每当打开或关闭包装的连接或您对其运行查询时,它都会被记录下来。您可以配置日志消息模板和其他设置,例如是否保存 SQL 参数。还保存了经过的时间。
在我看来,唯一的缺点是文档很少,但我认为这只是因为它是一个新项目(在撰写本文时)。我不得不深入研究一下 repo 以了解它并根据我的喜好对其进行配置,但现在它运行良好。
来自文档:
该工具由
DbConnection和DbCommand跟踪执行时间并将消息写入ILogger<T>。ILogger<T>可以由任何日志框架处理 (例如 Serilog)。结果类似于默认的 EF Core 日志记录 行为。lib 声明了一个帮助方法来注册
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()) { //... }
【讨论】:
只是在这里添加一个更新,因为我看到这个问题仍然有很多点击 - 这些天我使用Glimpse(现在似乎已经死了)或Stackify Prefix,它们都具有 sql 命令跟踪功能。
当我问原始问题时,这并不是我想要的,而是解决了同样的问题。
【讨论】: