Click here to Skip to main content
15,891,687 members
Articles / Programming Languages / SQL

Logging NHibernate Queries with Parameters

Rate me:
Please Sign up or sign in to vote.
3.50/5 (3 votes)
4 Sep 2011CPOL1 min read 21.7K   2   1
Logging NHibernate queries with parameters

NHibernate lets you log the SQL statements it constructs using log4net. I’m not going to explain how to do it, because it is already well explained. It gives you flexibility on where you want to log: console, text file, XML file, etc. The output that you get looks something like this:

SQL
12:33:54,464 DEBUG SQL:56 -
SELECT
    count(CategoryId)
FROM
    ProductCategories
WHERE
    ProductId=@p0;
 @p0 = 65536 [Type: Int32 (0)]

Notice that the query contains parameter name, not value – values are listed on the bottom.

Sometimes, you want to run this query using a tool other than NHibernate, SQL Server Management Studio, for example. Then, you’ll have to copy the appropriate parameter values and replace it in a query. Doing it by hand is a waste of time, so I wrote a custom log4net appender, that does it for us. Here’s the source code:

C#
public class NHAppender: ForwardingAppender
{
	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));
	}

	private static string ReplaceQueryParametersWithValues(string query)
	{
		return 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();
		});
	}
}

What I’ve done here is derive from a ForwardingAppender, that lets you transform the output logged and forward it to another appender. The NHAppender replaces the parameter names in query (@p0, @p1 and so on) with appropriate values, taking batch commands into account (notice the usage of Regex.Split).

You can use this appender to forward fully executable SQL queries to the console like this in your configuration:

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

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

This way, you can copy the queries from console output and execute it immediately.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Lithuania Lithuania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Taha Zubair Ahmed1-Mar-12 0:11
Taha Zubair Ahmed1-Mar-12 0:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.