简体   繁体   English

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

[英]Execute NHibernate-generated prepared statements in SQL Server Management Studio

Configuring NHibernate to display executed SQL does what it's supposed to, but whenever a SQL string needs to be copy-pasted into SQL Server Management Studio, we have to rearrange it dramatically in order to be compatible. 配置NHibernate以显示已执行的SQL可以实现预期,但每当需要将SQL字符串复制粘贴到SQL Server Management Studio时,我们必须重新排列它以便兼容。

Before I dive into developing my own application that parses and rearranges this into a more ManagementStudio-friendly SQL, I'd like to reassert that this hasn't been done before - I'd hate to spend time on this and find out later. 在我开始开发我自己的应用程序之前,将其解析并重新排列为更适合管理工作室的SQL之前,我想重申以前没有这样做过 - 我不想花时间在这上面找出来。

Is there a cheap and practicable way of converting the NH-generated prepared statement into something that's executable straight away? 是否有一种廉价且切实可行的方法将NH生成的预处理语句转换为可立即执行的语句?

Thanks in advance 提前致谢

I know you can do this with nhibernate profiler but this is not a free tool. 我知道你可以用nhibernate profiler做到这一点,但这不是一个免费的工具。 I would also be interested in a free alternative to doing this. 我也有兴趣免费替代这样做。

http://nhprof.com/ http://nhprof.com/

Edit 编辑

Looks like there is a custom appender out there for log4net that will format it such that you can actually run the sql NHibernate spits out. 看起来有一个自定义的appender用于log4net,它将格式化它,这样你就可以实际运行sql NHibernate spits了。 I saw it in the blog listed below: 我在下面列出的博客中看到了它:

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

Below is the code I have taken from the above blog and modified to work with Guids: 下面是我从上面的博客中获取的代码,并修改为与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();
    }
}

Here is how you would send this output to the console: 以下是将此输出发送到控制台的方法:

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

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

NOTE: 注意:

It appears this causes some fairly significant performance issues in a production system. 这似乎会在生产系统中引起一些相当重要的性能问题。 I haven't found a better way to do this yet but for anyone using this beware of these performance issues 我还没有找到更好的方法来做到这一点,但对于任何使用它的人都要注意这些性能问题

I haven't used this in a while but I believe using an interceptor would fit your criteria. 我有一段时间没有使用它,但我相信使用拦截器符合你的标准。

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

Credit goes to user mindplay.dk here . 信用转到用户mindplay.dk 这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM