1

We're using NHibernate 3.2.

I'd like to be able to log SQL queries from a specific ISession. Is that possible?

Alternatively, if that is not possible, could I set a logger to a specific ISessionFactory? Then I could create this ISession from this specific factory.

From what I saw, to set the logger, you have to do something like that:

<appSettings>
       <add key="nhibernate-logger" value="NH3SQLLogger.LoggerFactory, NH3SQLLogger" />
</appSettings>    

However, that would make the setting global for all the factories.

Could I do something like that:

        var config = new Configuration();
        config.Configure();
        config.SetProperty("nhibernate-logger",
                       "NH3SQLLogger.LoggerFactory, NH3SQLLogger");
        _sessionFactory = config.BuildSessionFactory();

Would that work? Or is there another way?

VitalyB
  • 12,397
  • 9
  • 72
  • 94

1 Answers1

4

No, you can only specify a logger globally. To do what you want would be fairly complicated.

You would need to:

  1. Write your own ILoggerFactory implementation
  2. Capture logging data from NHibernate.SQL to capture all SQL
  3. Capture logging data from NHibernate.Impl.SessionImpl to capture which ISession and ISessionFactory generated the SQL.
  4. Code the logic to ignore all SQL except that generated by your named ISessionFactory.

Here's some code to get you started:

public class LoggerFactory : ILoggerFactory
{
    #region Implementation of ILoggerFactory

    /// <summary>
    /// Returns the logger for a given key name
    /// </summary>
    /// <param name="keyName">Key or class name</param>
    /// <returns>Logger</returns>
    public IInternalLogger LoggerFor( string keyName )
    {
        if ( string.IsNullOrWhiteSpace( keyName ) )
            return new NoLoggingInternalLogger();

        switch ( keyName )
        {
            case "NHibernate.SQL":
                return new SqlLogger(); // Create this class to capture the SQL
            case "NHibernate.Impl.SessionImpl":
                return new SessionLogger(); // Create this class to capture ISession-related stuff
            default:
                return new NoLoggingInternalLogger();
        }
    }

    /// <summary>
    /// Returns the logger for a given type
    /// </summary>
    /// <param name="type">Class name</param>
    /// <returns>Logger</returns>
    public IInternalLogger LoggerFor( Type type )
    {
        return LoggerFor( type.FullName );
    }

    #endregion Implementation of ILoggerFactory
}
Randy Burden
  • 2,611
  • 1
  • 26
  • 34
  • Thanks for the detailed answer, Randy. I am a bit wary of this solution, however, since it would mean that this logger will execute for every session in the system, which would result in a global performance hit. Is there no other way (e.g without logging) to get the full SQL from a specific session? – VitalyB Mar 29 '13 at 02:05
  • Also, if you could please take a look at this, follow-up question: http://stackoverflow.com/questions/15700406/getting-building-the-sql-with-parameters-from-nhibernate-3-2 Thanks! – VitalyB Mar 29 '13 at 09:15
  • 1
    @VitalyB Unfortunately, I don't know of any other way to gain access to the full SQL query string and parameters. And yes, creating a customer ILoggerFactory will result in some kind of performance hit. I took at look at your follow-up question too but I don't have anything else to contribute as I've never had to do anything quite like that. Good luck to you though! – Randy Burden Mar 30 '13 at 05:21