【问题标题】:How to log/get a SQL query auto-generated by Dapper Extensions?如何记录/获取 Dapper Extensions 自动生成的 SQL 查询?
【发布时间】:2017-05-25 14:57:33
【问题描述】:

我使用 Dapper Extensions (DE) 作为 ORM。它在使用存储库模式实现的数据访问层中使用。 SQL Express 是后端 RDBMS。

DE 会自动为我生成大部分查询。我想记录这些自动生成的查询以进行调试。

我认为有两种方法可以实现这一目标:-

  1. 获取 DE 生成的 SQL 查询(在执行之前或之后)并将其写入日志。 这对我来说是首选方式,因为我已经有了我的日志记录模块(使用 log4net)。我唯一需要的是 DE 生成的 SQL。
  2. 将 DE 与某些日志记录工具集成。我读了this 的答案。看起来可以使用 MiniProfiler 工具;但正如我上面所说,我已经有了我的日志记录模块。我不想使用其他工具来记录 SQL 查询。

如何在不使用任何其他日志记录工具的情况下记录/获取 Dapper Extensions 自动生成的 SQL 查询?

other 的类似问题是关于 Dapper。这个问题是关于 Dapper Extensions 的。

【问题讨论】:

  • @DaveInCaz:这绝不是重复的。 1) 这个问题是关于 Dapper 的;这是关于 Dapper 扩展的。 2)我已经阅读了该问题并在底部的问题中提到了它;请看一看。 3)虽然我在这里的一个答案归结为 Dapper 唯一的解决方案,但其他答案是明确的 Dapper Extensions。
  • 如果您使用 MSSQL SQL Server Profiler 将是一个很好的方式,无需向您的项目添加任何依赖项。

标签: c# dapper dapper-extensions


【解决方案1】:

查看来自@MarcGravell 的commentthis 关于对Dapper 执行相同操作的问题,MiniProfiler.Integrations 是为 Dapper 扩展实现日志记录的更好方法。

以上链接的问题是关于 Dapper。但是 Dapper Extensions 在内部使用 Dapper。因此,如果为 Dapper 实现了日志记录,那么同样适用于 Dapper Extensions。

更多详情请访问GitHub

示例代码如下:

var factory = new SqlServerDbConnectionFactory(connectionString);
CustomDbProfiler cp = new CustomDbProfiler();
using(var connection = DbConnectionFactoryHelper.New(factory, cp))
{
    //DB Code
}
string log = cp.ProfilerContext.GetCommands();

如果适合您的需要,您可以使用内置 CustomDbProfilerCustomDbProfiler.Current。无论您调用该方法多少次,cp.ProfilerContext.GetCommands() 都会返回所有命令(成功和失败)。我不确定,但它可能在内部维护连接字符串(StringBuilder 可能是)。如果是这种情况,这可能会降低性能。但是,就我而言,默认情况下禁用日志记录。我只在需要调试某些东西时启用日志记录。所以这对我来说不是问题。

如果在非常大的范围内使用单个连接,这也可能会引发内存占用问题。为避免这种情况,请确保正确处理 CustomDbProfiler 实例。

如问题所述,最初,我想避免这种方式(使用外部工具/库)。但是,MiniProfiler.Integrations 并没有写入日志本身。我可以简单地获取所有生成的查询并将它们提供给我的记录器模块以转储到文件中。这就是为什么,这看起来更适合我。


MiniProfiler.dll 在内部实现了类似的逻辑(在StackExchange.Profiling.Data.ProfiledDbConnectionStackExchange.Profiling.Data.ProfiledDbCommand 类中),在herehere 中提到。所以,如果我决定(将来可能)绕过 MiniProfiler,我可以自己使用这个实现。

【讨论】:

    【解决方案2】:

    Dapper Extensions 项目是开源的;每个人都知道。我从 GitHub 上下载了它,并对其进行了修改以满足我的需要。

    Dapper Extensions 在 SqlGeneratorImpl 类内部构建/生成 SQL 查询。此类中有多种方法可以生成各种查询。

    我在DapperExtensions.DapperExtensions static 类中添加了以下属性:

    static string lastGeneratedQuery;
    public static string LastGeneratedQuery
    {
        get
        {
            lock(_lock)
            {
                return lastGeneratedQuery;
            }
        }
        internal set
        {
            lock(_lock)
            {
                lastGeneratedQuery = value;
            }
        }
    }
    

    另外,在SqlGeneratorImpl类的各种方法中设置这个属性。以下是我如何在Select 方法中设置的示例。

    public virtual string Select(IClassMapper classMap, IPredicate predicate, IList<ISort> sort, IDictionary<string, object> parameters)
    {
        ......
        ......
    
        StringBuilder sql = new StringBuilder(string.Format("SELECT {0} FROM {1}",
        ......
        ......
    
        DapperExtensions.LastGeneratedQuery = sql.ToString();
    
        return sql.ToString();
    }
    

    基本测试运行良好;我还没有彻底测试过。如果有任何变化,我会更新这个答案。

    请注意,我不建议将此作为标准解决方案;这只是一个适合我需要的技巧。我真的很想将其视为图书馆的常规功能。 如果您有更好的解决方案,请发布答案。否则,请评论以改进解决方案此处建议。

    this pull request 合并到master 分支后,希望现在可以立即使用,无需再下载和修改工具包源代码。请注意,我尚未对此进行验证。

    【讨论】:

    • 很公平 :) 我个人还是会使用 miniprofiler,但我想我们已经在使用它了...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2014-01-12
    • 1970-01-01
    相关资源
    最近更新 更多