【问题标题】:Execute NHibernate-generated prepared statements in SQL Server Management Studio在 SQL Server Management Studio 中执行 NHibernate 生成的预处理语句
【发布时间】:2012-06-13 12:39:14
【问题描述】:

将 NHibernate 配置为显示已执行的 SQL 完成了它应该做的事情,但是每当需要将 SQL 字符串复制粘贴到 SQL Server Management Studio 中时,我们必须对其进行大幅重新排列以使其兼容。

在我开始开发自己的应用程序以将其解析并重新排列为更适合 ManagementStudio 的 SQL 之前,我想重申以前没有这样做过 - 我不想花时间在这上面并找到稍后出。

是否有一种廉价且实用的方法可以将 NH 生成的准备好的语句转换为可以立即执行的语句?

提前致谢

【问题讨论】:

  • 我在下面发布了对我的答案的编辑。如果可行并且您使用的是 log4net,这似乎是一个不错的解决方案。

标签: sql sql-server-2008 nhibernate prepared-statement


【解决方案1】:

我知道你可以使用 nhibernate profiler 来做到这一点,但这不是一个免费的工具。我也对这样做的免费替代方案感兴趣。

http://nhprof.com/

编辑

看起来有一个用于 log4net 的自定义附加程序,它将对其进行格式化,以便您可以实际运行 sql NHibernate 吐出。我在下面列出的博客中看到了它:

http://gedgei.wordpress.com/2011/09/03/logging-nhibernate-queries-with-parameters/

以下是我从上面的博客中获取并修改以使用 Guids 的代码:

/// <summary>
/// This log4net appender is used for outputting NHibernate sql statements in a sql management studio friendly format.
/// This means you should be able to copy the sql output from this appender and run it directly.  Normally in the NHibernate
/// output there is parameterized sql that must be manually edited to run it.
/// </summary>
public class NHibernateSqlAppender : ForwardingAppender
{
    private const string GuidRegex = @"\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b";

    protected override void Append(LoggingEvent loggingEvent)
    {
        var loggingEventData = loggingEvent.GetLoggingEventData();

        if (loggingEventData.Message.Contains("@p"))
        {
            StringBuilder messageBuilder = new StringBuilder();

            string message = loggingEventData.Message;
            var queries = Regex.Split(message, @"command\s\d+:");

            foreach (var query in queries)
                messageBuilder.Append(ReplaceQueryParametersWithValues(query));

            loggingEventData.Message = messageBuilder.ToString();
        }

        base.Append(new LoggingEvent(loggingEventData));
    }

    public static string ReplaceQueryParametersWithValues(string query)
    {
        string returnQuery = Regex.Replace(query, @"@p\d+(?=[,);\s])(?!\s*=)", match =>
        {
            Regex parameterValueRegex = new Regex(string.Format(@".*{0}\s*=\s*(.*?)\s*[\[].*", match));
            return parameterValueRegex.Match(query).Groups[1].ToString();
        });

        //Place single quotes around all Guids in the sql string
        returnQuery = Regex.Replace(returnQuery, GuidRegex, "'$0'", RegexOptions.IgnoreCase);

        int parameterListIndex = returnQuery.LastIndexOf("@p0");

        if (parameterListIndex != -1)
        {
            //Truncate the paramter list off the end since we are substituting the actual values in the regular expression above
            //The -1 also cuts off the semicolon at the end
            return returnQuery.Substring(0, parameterListIndex).Trim();
        }

        return returnQuery.Trim();
    }
}

以下是将此输出发送到控制台的方式:

<appender name="NHibernateSqlAppender" type="NHibernatePlayground.Custom.NHibernateSqlAppender, NHibernatePlayground">
    <appender-ref ref="console" />
</appender>

<root>
    <appender-ref ref="NHibernateSqlAppender" />
</root>

注意:

这似乎会在生产系统中引起一些相当严重的性能问题。我还没有找到更好的方法来做到这一点,但任何使用它的人都要小心这些性能问题

【讨论】:

  • 我还在ReplaceQueryParametersWithValues 的博文中做了一个小补充。最后,我添加了在所有 Guid 值周围加上单引号的功能,以便您可以更轻松地运行查询。
  • 谢谢,这对我来说是一个可行的选择!
  • 再次编辑以使用超过 10 个参数,并在最后截断所有参数。
  • @ColeW:请您包括“GuidRegex”的定义吗?
  • @demoncodemonkey 已经很久了,但我刚刚注意到你的评论。我终于包含了 GuidRegex 常量以及我用来执行此操作的完整类。
【解决方案2】:

我已经有一段时间没有使用它了,但我相信使用拦截器会符合您的标准。

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

功劳归用户mindplay.dkhere

【讨论】:

  • 我不需要重新路由输出,我正在寻找一种轻松执行诸如select * from foo where bar=@p0;@p0='baz'[String(20)]之类的方法
猜你喜欢
  • 1970-01-01
  • 2014-02-18
  • 2012-03-14
  • 1970-01-01
  • 2012-11-18
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多