NHibernate - 如何使用参数值记录命名参数化查询?

Posted

技术标签:

【中文标题】NHibernate - 如何使用参数值记录命名参数化查询?【英文标题】:NHibernate - How to log Named Parameterised Query with parameter values? 【发布时间】:2019-06-08 11:28:47 【问题描述】:

我有一个这样的参数化命名查询:

Query moveOutQuery = session.createSQLQuery(moveOutQueryStr.toString())
                .addEntity(MyClass.class)
                .setParameter("assignmentStatus", Constants.CHECKED_OUT)

我想查看填充参数的实际 SQL 查询。但是在调试时我只得到以下查询:

Select * from my_assignment WHERE assignment_status in ( :assignmentStatus )

为什么assignmentStatus 没有被替换为它的真正价值?

【问题讨论】:

【参考方案1】:

为什么没有用 assignmentStatus 代替它的实际值?

这是因为 NHibernate 使用查询参数来输入值。这在 许多 情况下是有效的,也有助于抵御 SQL 注入攻击。参数单独发送。如果按照下面的说明记录了 SQL,您可以在底部找到它们。


您可以将每个 SQL 记录到文件中,如下所述。

这是通过log4net.dll实现的;您需要添加参考。

如下添加命名空间:

using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;

在NHibernate中配置log4net如下:

Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.Root.RemoveAllAppenders();

FileAppender fileAppender = new FileAppender();
fileAppender.Name = "NHFileAppender";
fileAppender.File = logFilePath;
fileAppender.AppendToFile = true;
fileAppender.LockingModel = new FileAppender.MinimalLock();
fileAppender.Layout = new PatternLayout("%dyyyy-MM-dd HH:mm:ss:%m%n%n");
fileAppender.ActivateOptions();

Logger logger = hierarchy.GetLogger("NHibernate.SQL") as Logger;
logger.Additivity = false;
logger.Level = Level.Debug;
logger.AddAppender(fileAppender);

hierarchy.Configured = true;

配置时还需要设置ShowSql

configuration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true");
configuration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "true");

您需要在应用程序启动时调用此代码一次。输出日志也包括参数值。

以下是代码:

session.CreateSQLQuery("SELECT * FROM MyEntity WHERE MyProperty = :MyProperty")
            .AddEntity(typeof(MyEntity))
            .SetParameter("MyProperty", "filterValue")
            .UniqueResult<MyEntity>();

以下是记录的查询:

2020-01-09 14:25:39:
    SELECT
        * 
    FROM
        MyEntity 
    WHERE
        MyProperty = @p0;
    @p0 = 'filterValue' [Type: String (4000:0:0)]

如你所见,参数值filterValue列在底部。

这适用于所有查询 API,例如 IQueryOverIQueryISQLQuery 等。

这会记录成功和失败的语句。您可以使用FileAppenderLogger 类来满足您的额外要求。

另请参阅 PatternLayout 和 documentation。更多细节也可以在here、here和here找到。 This Q/A 讨论了同样的问题。

以下问答也可能有所帮助:

Get executed SQL from nHibernate Using log4net to write to different loggers How to log SQL calls with NHibernate to the console of Visual Studio?

如您所见,这会在查询底部记录参数值。如果您希望将这些记录嵌入到查询中,请参阅this 文章。

【讨论】:

以上是关于NHibernate - 如何使用参数值记录命名参数化查询?的主要内容,如果未能解决你的问题,请参考以下文章

在 NHibernate 中使用命名参数作为表名

列错误中的冒号 ':' - 并非所有命名参数都已在 Nhibernate 中设置?

在 nhibernate 中使用参数值打印查询字符串?

如何从具有命名参数的表值函数创建 ADODB 记录集

第二十九天Python学习记录

如何在NHibernate Criteria Query中截断浮点值?