如何配置 Fluent NHibernate 以将查询输出到 Trace 或 Debug 而不是 Console?

Posted

技术标签:

【中文标题】如何配置 Fluent NHibernate 以将查询输出到 Trace 或 Debug 而不是 Console?【英文标题】:How to configure Fluent NHibernate to output queries to Trace or Debug instead of Console? 【发布时间】:2011-01-09 05:24:49 【问题描述】:

我正在使用MsSqlConfiguration.MsSql2008.ShowSql(),但它没有参数,我在 Google 上找不到任何东西。

【问题讨论】:

【参考方案1】:

我可以从随处可见的论坛和博客帖子中看到,在我之前的许多其他人已经在寻找一种方法来获取准备执行的 SQL 语句。答案通常类似于“你不能”或“你不应该”。

不管我是否应该,这就是我想要的。

经过数小时的搜索、调查和失败的尝试,我终于想出了这个。

编写一个拦截器:

using NHibernate;
using System.Diagnostics;

public class SqlStatementInterceptor : EmptyInterceptor

    public override NHibernate.SqlCommand.SqlString OnPrepareStatement(NHibernate.SqlCommand.SqlString sql)
    
        Trace.WriteLine(sql.ToString());
        return sql;
    

当然,您不必在这里Trace.WriteLine(),您可以将其写入日志文件,或者您需要的任何其他内容。

在您的连接管理器中,像这样连接您的拦截器:

protected virtual void Configure(FluentConfiguration config)

    config.ExposeConfiguration(x =>
                                   
                                       x.SetInterceptor(new SqlStatementInterceptor());
                                   );

没那么复杂。从我的角度来看,这肯定比试图通过 Fluent 将所有这些 XML 推送到 NHibernate 更容易——因为 Fluent 将 XML 文件抽象掉了。

请记住,您只能拥有一个拦截器 - 因此,如果您已经拥有一个拦截器,则可能需要将此功能与现有拦截器集成。在那张纸条上,您可能想给它一个更广泛的名称 - 例如MyAppInterceptor,以免暗示特定用途,因为您可能希望稍后向其添加其他功能。

【讨论】:

很好的解决方案,简单得像地狱一样,它就可以工作,将它添加到我的测试会话工厂中,尽管可以使用#if DEBUG 添加。谢谢! 也许也可以填写参数?我得到?(问号)而不是像SELECT * FROM MyObject WHERE Id = ? 这样的查询中的值。我看到有一个IEnumerable NHibernate.SqlCommand.SqlString.GetParameters() @Mike 将 sql.ToString() 替换为 base.OnPrepareStatement(sql) @mindplay.dk 我知道这是一个古老的答案,但base.OnPrepareStatement(sql) 仍然输出?s。有什么想法吗?【参考方案2】:

您可能想使用 log4net,而不是 ShowSql。以下是向 Debug 发送查询的一些配置:

  <configSections>
    <section name="log4net"
     type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>

  <log4net debug="false">
    <appender name="WindowsDebugOutput" type="log4net.Appender.DebugAppender,
         log4net">
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern"
              value="%dABSOLUTE %-5p %c1:%L - %m%n" />
      </layout>
    </appender>

    <logger name="NHibernate.SQL" additivity="false">
      <level value="DEBUG" />
      <appender-ref ref="WindowsDebugOutput" />
    </logger>
  </log4net>

然后在打开 NHibernate 会话之前从您的代码中调用它:

log4net.Config.XmlConfigurator.Configure();

当您添加对 log4net DLL 的引用时,请确保将其“Copy Local”属性设置为“true”。

这不是 FluentNHibernate 特有的,它在 NHibernate 的任何变体中都一样。

【讨论】:

Noobish 问题,但是,将这个配置文件放在 winforms 项目中的什么位置?很多 Hibernate 的文档网站都关闭了,我只是找不到将这些 XML 信息放在哪里。谢谢。 @Mike - 它应该进入项目根目录中的 app.config,在编译时将其作为 .exe.config 复制到 bin 目录。 很高兴对 3 岁以上的答案发表评论!非常感谢!【参考方案3】:

我没有在 SQL Server 上尝试过,但是在 SQLite 上,以下代码将在 Output 窗口中显示生成的 SQL(调试菜单 -> Windows -> 输出,在 VS2008 中)。

输出窗口中的“显示输出:”组合框应设置为“调试”-VS2008 自动为我完成了。

            sessionFactory = Fluently.Configure()
                .Database(SQLiteConfiguration.Standard
                            .UsingFile(DbFile)
                            // Display generated SQL in Output window
                            .ShowSql()
                          )
                .Mappings(m => m.AutoMappings.Add( GetAutoPersistenceModel() ))
                .BuildSessionFactory()
                ;

警告 - 开启此功能会大大减慢执行速度。

【讨论】:

Visual Studio 中的输出窗口显示控制台、调试和跟踪输出。 ShowSql 方法写入控制台,而不是 Debug 或 Trace。你的建议与他所说的他已经在做的没有什么不同。 @Michael - 我刚刚重新测试了这个,它完全按照描述工作! SQLite 与 SQL Server 的 FNH 接口实现可能存在差异? 这不是同一个“调试”(注意没有“跟踪”或“控制台”选项)。 :) 要查看它是否真正写入 Debug,请使用 technet.microsoft.com/en-us/sysinternals/bb896647.aspx

以上是关于如何配置 Fluent NHibernate 以将查询输出到 Trace 或 Debug 而不是 Console?的主要内容,如果未能解决你的问题,请参考以下文章

Fluent 映射和 NHibernate Xml 配置

Fluent Nhibernate 数据库配置

更改 NHibernate 中的初始 LazyLoad 行为

在使用fluent-nhibernate配置nhibernate时,为什么会出现MissingMethodException?

如何使用 Fluent-NHibernate 和 MySQL 指定自动递增 (int) 标识列

如何在 Fluent NHibernate ClassMap 类中指定表名?