小编典典

在SQL Server Management Studio中执行NHibernate生成的准备好的语句

sql

将NHibernate配置为显示执行的SQL可以完成预期的工作,但是每当需要将SQL字符串复制粘贴到SQL Server Management
Studio中时,为了使其兼容,我们都必须对其进行重新排列。

在开始开发自己的应用程序以将其解析并重新排列为对ManagementStudio更友好的SQL之前,我想重申一下以前从未做过的事情-
我不愿意花时间在此上,以后再查找。

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

提前致谢


阅读 206

收藏
2021-04-07

共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>

笔记:

看来这会在生产系统中引起一些相当严重的性能问题。我还没有找到更好的方法来执行此操作,但是对于使用此方法的任何人,请注意这些性能问题

2021-04-07