对新手而言NHibernate的调试事件很痛苦的事情,不知道NHibernate做了些什么,错误出现在什么地方。
我给出一些常用的调试办法希望对你有所帮助。
1.查看NHibernate写在控制台里的Sql语句
在配置文件中有这么个选项,如果把它设置为true,NHibernate会把执行的Sql显示在控制台上。
< property name ="show_sql" > true </ property > 对于控制台应用程序我们可以设置断点后很轻松的看到NHibernate执行了什么Sql。
下图是从数据库中读取一条数据。
如果你写了单元测试,从NUnit同样可以很容易地看到。
2.配置Log4net来查看NHibernate留下的日志 如果你的程序是Asp.Net程序。那就看不到控制台信息了。那么就使用第二招配置Log4net。
按习惯,我还是使用单独的配置文件。当然你也可以配置在应用程序配置文件中(App.config或Web.Config)。
<? xml version="1.0" encoding="utf-8" ?> < log4net > < appender name ="rollingFile" type ="log4net.Appender.RollingFileAppender,log4net" > < param name ="File" value ="log.txt" /> < param name ="AppendToFile" value ="false" /> < param name ="RollingStyle" value ="Date" /> < param name ="DatePattern" value ="yyyy.MM.dd" /> < param name ="StaticLogFileName" value ="true" /> < layout type ="log4net.Layout.PatternLayout,log4net" > < param name ="ConversionPattern" value ="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" /> </ layout > </ appender > < root > <!-- 如果只需要看看Sql设置INFO就够了,如果你要调试可以设置为DEBUG或ALL --> < priority value ="INFO" /> < appender-ref ref ="rollingFile" /> </ root > </ log4net > 读取log4net配置的代码
XmlConfigurator.Configure( new FileInfo( " log4net.cfg.xml " )); 运行了程序后你可以在应用程序目录找到log.txt的配置文件。里面记录了包括Sql的NHibernate的运行信息。
这是一个日志的片断
2006 - 08 - 08 22 : 22 : 16 , 921 [ 2036 ] INFO NHibernate.Cfg.Environment [ (null) ] <(null)> - NHibernate 1.0.2 2006 - 08 - 08 22 : 22 : 16 , 968 [ 2036 ] INFO NHibernate.Cfg.Environment [ (null) ] <(null)> - nhibernate section not found in application configuration file 2006 - 08 - 08 22 : 22 : 16 , 968 [ 2036 ] INFO NHibernate.Cfg.Environment [ (null) ] <(null)> - Using reflection optimizer 2006 - 08 - 08 22 : 22 : 17 , 000 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - Searching for mapped documents in assembly: DDLLY.MyDoc.NHibernateTest.Log4NetTest 2006 - 08 - 08 22 : 22 : 17 , 000 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - Found mapping documents in assembly: DDLLY.MyDoc.NHibernateTest.Log4NetTest.User.hbm.xml 2006 - 08 - 08 22 : 22 : 17 , 062 [ 2036 ] INFO NHibernate.Dialect.Dialect [ (null) ] <(null)> - Using dialect: NHibernate.Dialect.MsSql2000Dialect 2006 - 08 - 08 22 : 22 : 17 , 109 [ 2036 ] INFO NHibernate.Cfg.Binder [ (null) ] <(null)> - Mapping class: DDLLY.MyDoc.NHibernateTest.Log4NetTest.User -> users 2006 - 08 - 08 22 : 22 : 17 , 156 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - Configured SessionFactory: DDLLY.MyDoc.NHibernateTest.Log4NetTest 2006 - 08 - 08 22 : 22 : 17 , 171 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - processing one-to-many association mappings 2006 - 08 - 08 22 : 22 : 17 , 171 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - processing one-to-one association property references 2006 - 08 - 08 22 : 22 : 17 , 171 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - processing foreign key constraints 2006 - 08 - 08 22 : 22 : 17 , 187 [ 2036 ] INFO NHibernate.Dialect.Dialect [ (null) ] <(null)> - Using dialect: NHibernate.Dialect.MsSql2000Dialect 2006 - 08 - 08 22 : 22 : 17 , 187 [ 2036 ] INFO NHibernate.Cfg.SettingsFactory [ (null) ] <(null)> - use outer join fetching: True 2006 - 08 - 08 22 : 22 : 17 , 187 [ 2036 ] INFO NHibernate.Connection.ConnectionProviderFactory [ (null) ] <(null)> - Intitializing connection provider: NHibernate.Connection.DriverConnectionProvider 2006 - 08 - 08 22 : 22 : 17 , 187 [ 2036 ] INFO NHibernate.Connection.ConnectionProvider [ (null) ] <(null)> - Configuring ConnectionProvider 2006 - 08 - 08 22 : 22 : 17 , 187 [ 2036 ] INFO NHibernate.Cfg.SettingsFactory [ (null) ] <(null)> - Optimize cache for minimal puts: False 2006 - 08 - 08 22 : 22 : 17 , 203 [ 2036 ] INFO NHibernate.Cfg.SettingsFactory [ (null) ] <(null)> - echoing all SQL to stdout 2006 - 08 - 08 22 : 22 : 17 , 203 [ 2036 ] INFO NHibernate.Cfg.SettingsFactory [ (null) ] <(null)> - Query language substitutions: {false = 0 , no = 'N' , yes = 'Y' , true = 1 } 2006 - 08 - 08 22 : 22 : 17 , 203 [ 2036 ] INFO NHibernate.Cfg.SettingsFactory [ (null) ] <(null)> - cache provider: NHibernate.Cache.HashtableCacheProvider 2006 - 08 - 08 22 : 22 : 17 , 203 [ 2036 ] INFO NHibernate.Cfg.Configuration [ (null) ] <(null)> - instantiating and configuring caches 2006 - 08 - 08 22 : 22 : 17 , 218 [ 2036 ] INFO NHibernate.Impl.SessionFactoryImpl [ (null) ] <(null)> - building session factory 2006 - 08 - 08 22 : 22 : 17 , 812 [ 2036 ] INFO NHibernate.Impl.SessionFactoryObjectFactory [ (null) ] <(null)> - Factory name:DDLLY.MyDoc.NHibernateTest.Log4NetTest 2006 - 08 - 08 22 : 22 : 17 , 859 [ 2036 ] INFO NHibernate.Loader.Loader [ (null) ] <(null)> - SELECT user0_.Id as Id0_ , user0_.Email as Email0_ , user0_.UserName as UserName0_ , user0_.Password as Password0_ FROM users user0_ WHERE user0_.Id = @p0 从这个文件我们可以看到NHibernate都做了些什么(包括执行了什么Sql,看上面的最后一行)。
当你想更详细的信息可以把priority设置为ALL,这样可以看到所有信息。
提示:NHibernate会把一般信息记录为INFO,调试信息记录为Debug,错误信息记录为Error。
Log4Net中支持多个appender你可以也把日志记录到数据库等其他地方,请参看Log4Net的文档,这里不做讲解。
3.让NHibernate的日志不影响你使用Log4Net写日志
NHibernate总是会调用配置<root>里面的“appender-ref”来写配置。
所以如果你系统本省也使用了Log4Net记录日志,而不想让NHibernate的日志影响,则可以定义logger。
<? xml version="1.0" encoding="utf-8" ?> < log4net > < root > <!-- 如果只需要看看Sql设置INFO就够了,如果你要调试可以设置为DEBUG或ALL --> < priority value ="INFO" /> < appender-ref ref ="rollingFile" /> </ root > < logger name ="ApplicationInfoLog" > < level value ="INFO" /> < appender-ref ref ="rollingFile1" /> </ logger > < appender name ="rollingFile" type ="log4net.Appender.RollingFileAppender,log4net" > < param name ="File" value ="log.txt" /> < param name ="AppendToFile" value ="false" /> < param name ="RollingStyle" value ="Date" /> < param name ="DatePattern" value ="yyyy.MM.dd" /> < param name ="StaticLogFileName" value ="true" /> < layout type ="log4net.Layout.PatternLayout,log4net" > < param name ="ConversionPattern" value ="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" /> </ layout > </ appender > < appender name ="rollingFile1" type ="log4net.Appender.RollingFileAppender,log4net" > < param name ="File" value ="log1.txt" /> < param name ="AppendToFile" value ="false" /> < param name ="RollingStyle" value ="Date" /> < param name ="DatePattern" value ="yyyy.MM.dd" /> < param name ="StaticLogFileName" value ="true" /> < layout type ="log4net.Layout.PatternLayout,log4net" > < param name ="ConversionPattern" value ="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" /> </ layout > </ appender > </ log4net > 日志记录代码
ILog applicationInfoLog = applicationInfoLog = LogManager.GetLogger( " ApplicationInfoLog " );applicationInfoLog.Info( " 记录日志 " ); 此例中NHibernater日志会存在log.txt,系统日志记录在log1.txt。
4.在使用SqlServer时使用事件查看器监视Sql
对于SqlServer数据库,如果你没有条件可以完成上面的功能,那么你可以使用事件查看器来监视执行的Sql,使用比较简单,不多说了。