简体   繁体   English

如何记录/获取由 Dapper 扩展自动生成的 SQL 查询?

[英]How to log/get a SQL query auto-generated by Dapper Extensions?

I am using Dapper Extensions (DE) as ORM.我使用 Dapper Extensions (DE) 作为 ORM。 It is consumed in Data Access Layer which is implemented using Repository pattern.它在使用存储库模式实现的数据访问层中使用。 SQL Express is back-end RDBMS. SQL Express 是后端 RDBMS。

DE automatically generates most of the queries for me. DE 会自动为我生成大部分查询。 I want to log those auto-generated queries for debugging purpose.我想记录那些自动生成的查询以进行调试。

There are two ways I can see to achieve this: -我可以看到有两种方法可以实现这一目标:-

  1. Get the SQL query generated by DE (before or after it is executed) and write it to log.获取 DE 生成的 SQL 查询(在执行之前或之后)并将其写入日志。 This is preferred way for me as I already have my logging module (using log4net) in place.这对我来说是首选方式,因为我已经有了我的日志记录模块(使用 log4net)。 The only thing I need is the SQL generated by DE.我唯一需要的是 DE 生成的 SQL。
  2. Integrate DE with some logging tool.将 DE 与一些日志工具集成。 I read this answer.我读了这个答案。 It looks possible using MiniProfiler tool;使用 MiniProfiler 工具看起来可能; but as I said above, I already have my logging module in place.但正如我上面所说,我已经有了我的日志模块。 I do not want to use other tool just for logging SQL queries.我不想仅使用其他工具来记录 SQL 查询。

How to log/get a SQL query auto-generated by Dapper Extensions without using any other logging tool?如何在不使用任何其他日志记录工具的情况下记录/获取由 Dapper Extensions 自动生成的 SQL 查询?

The other similar question is about Dapper. 另一个类似的问题是关于 Dapper。 This question is about Dapper Extensions.这个问题是关于 Dapper 扩展的。

Dapper Extensions project is open source; Dapper Extensions 项目是开源的; everyone knows that.每个人都知道。 I downloaded it from GitHub and modified it to meet my needs.我是从 GitHub 上下载下来的,并根据自己的需要进行了修改。

Dapper Extensions build/generate SQL query internally in SqlGeneratorImpl class. Dapper 扩展在SqlGeneratorImpl类中内部构建/生成 SQL 查询。 There are multiple methods in this class those generate the various queries.此类中有多种方法可以生成各种查询。

I added following property in DapperExtensions.DapperExtensions static class:我在DapperExtensions.DapperExtensions static类中添加了以下属性:

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

Also, set this property in various methods of SqlGeneratorImpl class.此外,在SqlGeneratorImpl类的各种方法中设置此属性。 Following is an example how I set it in Select method.以下是我如何在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();
}

Basic tests run well;基本测试运行良好; I have not yet tested this thoroughly.我还没有彻底测试过。 I will update this answer in case of any change.如有任何更改,我将更新此答案。

Please note that I do not recommend this as standard solution; 请注意,我不建议将此作为标准解决方案; this is just a hack that works for my needs. 这只是一个适合我需要的黑客。 I would really like to see this as a regular feature in library. 我真的很想将其视为图书馆的常规功能。 Please post an answer if you have better solution. 如果您有更好的解决方案,请发布答案。 Otherwise, please comment to improve the solution suggested here. 否则, 请发表评论以改进此处建议 的解决方案

After merging this pull request in master branch, hopefully this is now available out of the box and no need to download and modify the toolkit source code anymore.master分支中合并此拉取请求后,希望现在可以开箱即用,不再需要下载和修改工具包源代码。 Note that I have not verified this.请注意,我尚未对此进行验证。

Looking at the comment from @MarcGravell and this question about doing the same with Dapper, MiniProfiler.Integrations is better way to implement logging for Dapper Extensions.纵观评论从@MarcGravell和做同样与小巧玲珑的问题, MiniProfiler.Integrations是落实日志记录小巧玲珑的扩展更好的办法。

Above linked question is about Dapper.上面链接的问题是关于 Dapper。 But Dapper Extensions uses Dapper internally.但是 Dapper Extensions 在内部使用 Dapper。 So, if logging is implemented for Dapper, same works for Dapper Extensions as well.因此,如果为 Dapper 实现了日志记录,那么同样适用于 Dapper 扩展。

More details could be found on GitHub .更多细节可以在GitHub找到

Sample code is as below:示例代码如下:

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

You can use in-build CustomDbProfiler using CustomDbProfiler.Current if that suits your need.如果满足您的需要,您可以使用CustomDbProfiler使用CustomDbProfiler.Current cp.ProfilerContext.GetCommands() will return ALL the commands (success and failed) no matter how many times you call the method.无论您调用该方法多少次, cp.ProfilerContext.GetCommands()都将返回所有命令(成功和失败)。 I am not sure but, it might be maintaining concatenated string ( StringBuilder may be) internally.我不确定但是,它可能在内部维护连接的字符串( StringBuilder可能是)。 If this is the case, this may slow down the performance.如果是这种情况,这可能会降低性能。 But, in my case, logging is disabled by default.但是,就我而言,默认情况下禁用日志记录。 I only enable logging when I need to debug something.我只在需要调试时启用日志记录。 So this is not a problem for me.所以这对我来说不是问题。

This also may raise memory footprint issue if single connection is used over very large scope.如果在非常大的范围内使用单个连接,这也可能会引发内存占用问题。 To avoid this, make sure CustomDbProfiler instance is disposed properly.为避免这种情况,请确保正确处理CustomDbProfiler实例。

As mentioned in question, initially, I wanted to avoid this way (using external tool/library) .如前所述,最初,我想避免这种方式(使用外部工具/库) But, MiniProfiler.Integrations is NOT writing the log itself.但是, MiniProfiler.Integrations不会写入日志本身。 I can simply get all the queries generated and provide those to my logger module to dump into the file.我可以简单地生成所有查询并将它们提供给我的记录器模块以转储到文件中。 That is why, this looks more suitable to me now.这就是为什么,这现在看起来更适合我。


MiniProfiler.dll internally implements similar logic (in StackExchange.Profiling.Data.ProfiledDbConnection and StackExchange.Profiling.Data.ProfiledDbCommand classes) which is mentioned here and here . MiniProfiler.dll 在内部实现了类似的逻辑(在StackExchange.Profiling.Data.ProfiledDbConnectionStackExchange.Profiling.Data.ProfiledDbCommand类中),这里这里提到。 So, if I decide to (in future may be) bypass MiniProfiler, I can use this implementation myself.所以,如果我决定(将来可能会)绕过 MiniProfiler,我可以自己使用这个实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM