How to configure Log4Net for use with NHibernate

Recently there was a question in the NHUser group about how to configure Log4Net to log the queries generated by NHibernate. First of all: you can get Log4Net here. There you also find the documentation. If you are not sure about details of the configuration shown below please refer to this documentation.

Running without Log4Net

If you only want NHibernate to log the queries it sends to the data source when running unit tests you don't have to configure Log4Net at all. It suffices to add the show_sql key to the NHibernate configuration. If you are using a separate xml file to configure NHibernate (e.g. the hibernate.cfg.xml) then its content might look similar to the one below

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">Server=(local);Database=NHibernateFAQ;Integrated Security=SSPI;</property>
    
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>

Now when running any unit test that involves NHibernate the queries generated by NHibernate will be logged in the output window (be it the unit test runner of Resharper or be it the Output Window of Visual Studio when you use TestDriven).

Logging with Log4Net

If you want to use Log4Net to collect logging information generated by NHibernate you have to add the necessary configuration to the config file of your application. If you want to log to two different targets (e.g. to the console and to a file) the relevant sections in your config file might look like follows

<configuration>
  ...
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>
  
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender, log4net">
      <layout type="log4net.Layout.PatternLayout, log4net">
        <param name="ConversionPattern" value="%d %p %m%n" />
      </layout>
    </appender>
 
    <appender name="RollingFile" type="log4net.Appender.RollingFileAppender,log4net" >
      <param name="File" value="log.txt" />
      <param name="AppendToFile" value="true" />
      <param name="DatePattern" value="yyyy.MM.dd" />
 
      <layout type="log4net.Layout.PatternLayout,log4net">
        <conversionPattern value="%d %p %m%n" />
      </layout>
    </appender>
    
    <root>
      <priority value="DEBUG" />
      <appender-ref ref="ConsoleAppender" />
    </root>
    ...
</configuration>

Here I define that all output with a priority of at least DEBUG goes to the console.

Now I have to tell my application that I want to use Log4Net. I can do that with an assembly level attribute. That is, you have to put the following code snippet somewhere in your application (e.g. the "Global. asax" if you are building a web application)

// Configure log4net using the .config file
[assembly: log4net.Config.XmlConfigurator(Watch = true)]

having done do we can now run a first unit test that accesses the database via NHibernate. The output generated by Log4Net in the unit test runner is similar to this

2008-07-02 08:40:07,249 INFO NHibernate 2.0.0.1001 (2.0.0.1001)
2008-07-02 08:40:07,251 INFO hibernate-configuration section not found in application configuration file
2008-07-02 08:40:07,254 INFO Bytecode provider name : lcg
2008-07-02 08:40:07,257 INFO Using reflection optimizer
2008-07-02 08:40:08,515 DEBUG connection.provider=NHibernate.Connection.DriverConnectionProvider
2008-07-02 08:40:08,516 DEBUG dialect=NHibernate.Dialect.MsSql2005Dialect
2008-07-02 08:40:08,517 DEBUG connection.driver_class=NHibernate.Driver.SqlClientDriver
2008-07-02 08:40:08,517 DEBUG connection.connection_string=Server=(local);Database=NHibernateFAQ;Integrated Security=SSPI;
2008-07-02 08:40:08,518 DEBUG show_sql=false
2008-07-02 08:40:08,522 DEBUG properties: System.Collections.Generic.Dictionary`2[System.String,System.String]
2008-07-02 08:40:08,526 INFO Mapping resource: LoggingSample.Person.hbm.xml
2008-07-02 08:40:08,872 INFO Using dialect: NHibernate.Dialect.MsSql2005Dialect
2008-07-02 08:40:11,425 INFO Mapping class: LoggingSample.Person -> Person
2008-07-02 08:40:11,537 DEBUG Mapped property: Id -> Id, type: Int32
2008-07-02 08:40:11,612 DEBUG Mapped property: LastName -> LastName, type: String
2008-07-02 08:40:11,614 DEBUG Mapped property: FirstName -> FirstName, type: String
2008-07-02 08:40:11,614 DEBUG Mapped property: Birthdate -> Birthdate, type: DateTime
2008-07-02 08:40:11,632 INFO checking mappings queue
2008-07-02 08:40:11,634 INFO processing one-to-many association mappings
2008-07-02 08:40:11,634 INFO processing one-to-one association property references
2008-07-02 08:40:11,634 INFO processing foreign key constraints
2008-07-02 08:40:11,712 INFO Using dialect: NHibernate.Dialect.MsSql2005Dialect
2008-07-02 08:40:11,716 INFO Using dialect defined converter
...
2008-07-02 08:40:12,410 DEBUG Static SQL for entity: LoggingSample.Person
2008-07-02 08:40:12,411 DEBUG  Version select: SELECT Id FROM Person WHERE Id = ?
2008-07-02 08:40:12,412 DEBUG  Snapshot select: SELECT person_.Id, person_.LastName as LastName0_, person_.FirstName as FirstName0_, person_.Birthdate as Birthdate0_ FROM Person person_ WHERE person_.Id=?
...

as you can see LOADS of information.

To tune the generated logging information a little bit we can filter the output generated by NHibernate by putting the following configuration section into our config file (put them just after the root section inside the log4net node)

<logger name="NHibernate" additivity="false">
  <level value="WARN"/>      
  <appender-ref ref="RollingFile" />
  <appender-ref ref="ConsoleAppender" />
</logger>
 
<logger name="NHibernate.SQL" additivity="false">
  <level value="ALL"/>      
  <appender-ref ref="RollingFile" />
  <appender-ref ref="ConsoleAppender" />
</logger>

Obviously NHibernate defines two different loggers NHibernate and NHibernate.SQL. The first one receives all logging output that NHibernate generates where as the second one only receives the sql statements generated by NHibernate.

With the above settings in place the output generated is reduced to

2008-07-02 08:48:58,636 DEBUG select person0_.Id as Id0_, 
                        person0_.LastName as LastName0_, 
                        person0_.FirstName as FirstName0_, 
                        person0_.Birthdate as Birthdate0_ 
                        from Person person0_

That's what we want. Only if we have some weird problems we need to change the priority level of the NHibernate filter to say INFO or DEBUG.

As usual you can find a demo solution here.

Enjoy

Blog Signature Gabriel .

Print | posted on Tuesday, July 01, 2008 7:07 PM

Comments on this post

# re: How to configure Log4Net for use with NHibernate

Requesting Gravatar...
I have been unable to get any logging output from my Integration Test project.

I copied your log4net section and put it in the app.config for the IntegrationTest project.

I put the assembly attribute on the class file with the tests I'm executing and in the assemblyinfo.cs file of both the test project and the domain assembly.

Is there something else I'm doing wrong?

Thank you for the great content, it is extremely helpful.
Left by John on Jul 02, 2008 2:04 AM

# re: How to configure Log4Net for use with NHibernate

Requesting Gravatar...
@John: did you have a look at the demo solution I provide with this post? Does this one work for you?
Left by Gabriel Schenker on Jul 02, 2008 4:35 PM

# re: How to configure Log4Net for use with NHibernate

Requesting Gravatar...
Is this specific to NHibernate 2.0 ? It doesn't seem to be working with 1.2.0
Left by kk on Jul 10, 2008 4:03 AM

# re: How to configure Log4Net for use with NHibernate

Requesting Gravatar...
@kk: not that I am aware of... Can you provide some more details about your problem?
Left by Gabriel Schenker on Jul 20, 2008 6:05 PM

# how could connect two different Database

Requesting Gravatar...
hi
my name is zahra ,
i have two database that one tabel of one database have one to many relation with one tabel of another database ,if would you please help me how set connection string and session factory for each database.
thank you
Left by zahra on Oct 23, 2008 4:48 AM

# re: How to configure Log4Net for use with NHibernate

Requesting Gravatar...
@zahra: assuming that the two tables are in two different tables of the same sql server you would IIRC have to use the notation "databasename.schema.tablename" when mapping the entities
Left by nhibernate on Oct 27, 2008 6:15 PM

# re: How to configure Log4Net for use with NHibernate

Requesting Gravatar...
Logging in this manner does not seem to work inside of the integrated test suite of VSTS (MSTest?). The suggested configuration works if it's part of any other project, be it web, console, or WinForm though. I suspect it has something to do with the context MSTest uses to run in. I never did figure out a fix for this.
Left by Jamison Roberts on Dec 03, 2008 4:07 AM

Your comment:

 (will show your gravatar)
 
Please add 6 and 5 and type the answer here: