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

时间:2017-05-25 14:57:34

标签: c# dapper dapper-extensions

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

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

我可以通过两种方式来实现这一目标: -

  1. 获取DE生成的SQL查询(在执行之前或之后)并将其写入日志。 这是我的首选方式,因为我已经拥有了我的日志记录模块(使用log4net)。我唯一需要的是DE生成的SQL。
  2. 将DE与某些日志工具集成。我看了this回答。使用MiniProfiler工具看起来很可能;但正如我上面所说,我已经有了我的记录模块。我不想仅使用其他工具来记录SQL查询。
  3. 如何在不使用任何其他日志记录工具的情况下记录/获取Dapper Extensions自动生成的SQL查询?

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

2 个答案:

答案 0 :(得分:4)

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();
}

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

  

请注意,我不建议将其作为标准解决方案;这只是一个适合我需求的黑客。我真的希望将其视为库中的常规功能。 如果您有更好的解决方案,请发回答。否则,请评论以改进此处建议的解决方案

答案 1 :(得分:3)

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

以上链接的问题是关于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();

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

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

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

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