我使用Dapper Extensions(DE)作为ORM。它在使用Repository模式实现的数据访问层中使用。 SQL Express是后端RDBMS。
DE会自动为我生成大部分查询。我想记录这些自动生成的查询以进行调试。
我可以通过两种方式来实现这一目标: -
答案 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的comment和this关于对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.ProfiledDbConnection
和StackExchange.Profiling.Data.ProfiledDbCommand
类中),提到here和here。所以,如果我决定(将来可能)绕过MiniProfiler,我可以自己使用这个实现。