Execute NHibernate-generated prepared statements in SQL Server Management Studio

前端 未结 2 750
北荒
北荒 2021-01-14 08:00

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 r

相关标签:
2条回答
  • 2021-01-14 08:08

    I know you can do this with nhibernate profiler but this is not a free tool. I would also be interested in a free alternative to doing this.

    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. I saw it in the blog listed below:

    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:

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

    0 讨论(0)
  • 2021-01-14 08:33

    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.

    0 讨论(0)
提交回复
热议问题