Nhibernate全面分析NHibernate是一个基于.Net的针对关系型数据库的对象持久化类库.Nhibernate来源于非常优秀的基于Java的Hibernate关系型持久化工具.NHibernate源码分析之开篇:计划和安排只从使用NHibernate以来,请被其强大的功能和使用的简洁所吸引.为了进一步研究NHibernate,决定分析其源代码,如有感兴趣者,欢迎一起研究.这里列出了将要分析的部分:官方源码下载地址:配置和持久对象映射文件NHibernate配置有三种方式来存放nhibernate的配置1,作为单独的一节放在相应程序的配置文件中,对于执行文件或类库为文件名称后加.config,对于asp.net则是放在web.config中.这种方式必须在配置文件的configSetions中声明nhibernate的配置节,配置内容由Cfg.Environment类来读取,该类所有成员均为静态的,另外它还定义了配置中key值的常数.2.放在一个单独的配置文件中,默认为hibernate.cfg.xml,使用时必须调用Cfg.Configuration.Config().如不是默认的配置文件名,还必须指明配置文件名称.这种方式最适合多数据库的情况,可以为每个数据库建立一个配置文件.3.手工在程序中加入,配置内容最后将加入到Cfg.Configuration.Properties属性中,此属性为一IDictionary对象,并且为public,其余的就不用多话了吧.下面对几个重要的key值说明一下:hibernate.connection.provider连接提供者,取值必须是实现了IConnectionProvider接口的类的全名,当前版本只能取值NHibernate.Connection.DriverConnectionProvider;hibernate.connection.driver_class数据驱动类,取值必须是实现了IDriver接口的类的全名,常用的选择有NHibernate.Driver.SqlClientDriver,NHibernate.Driver.OleDbDriver等;hibernate.dialect数据库方言,取值必须是继承之Dialect的类的全名,最常用的就是NHibernate.Dialect.MsSql2000Dialect了,其它的没用过,不清楚能不能正常使用;hibernate.connection.connection_string连接字符串,取值与driver_class对应即可;hibernate.show_sql指明是否在log4net日志中显示sql语句,主要用于调试,取值为true或false;完整的配置key列表请查看Cfg.Environment类中的常数声明.持久对象映射文件nhibernate为我们提供了很多方式将持久对象映射文件加入到Cfg.Configuration类,下面将其一一列出:AddXmlFile:加入包括对象映射信息的文件;AddXmlString:加入包含映射信息的字符串;AddDocument:加入包含映射信息的Xmldocument;AddInputStream:加入包含映射信息的输入流;AddXmlReader:加入包含映射信息的XmlReader;AddResource:加入指定程序集的映射信息资源;AddClass:加入以类名指定的映射信息资源,映射文件必须为classname.hbm.xml;AddAssembly:加入指定程序集名称的映射信息资源注意:如果映射信息为文件形式,包括加入到程序集资源的文件,那么文件名必须以.hbm.xml结尾.NHibernate架构分析uml图从图中可以看到,Session和SessionFactory是NHibernate的核心部分.SessionFactory维护到持久机制(数据库)的连接并对它们进行管理,同时还保存着所有持久对象的映射信息.SessionFactory由Configuration.BuildSessionFactory创建,这个对象一般使用Singleton模式.Session用于将对象持久化,支持数据库事务,另外Session还提供了强大的数据加载功能.Session由SessionFactory创建.其它对象说明:IConnectionProvider:连接提供者接口,负责与数据进行连接;Dialect:数据库方言;CollectionPersister:集合持久化类;IClassPersister:类持久化接口,定义了基本的CRUD操作;TransactionFactory:数据库事务工厂;IInterceptor:拦截器接口,用于在操作执行时进行一些处理,典型的就是记录操作日志;NHibernate源码分析之一:配置信息配置信息用于指定NH以何种方式访问数据库,根据这些配置信息,NH动态的创建数据访问对象并与数据库进行交互.除了.net类库自带的Odbc,OleDb,OracleClient和SqlClient访问方式外,在0.2版中,NH增加了用于访问MySQL和Firebird的访问方式,这两种访问方式由第三方组件提供,mono的用户应该高兴了.:)NH的配置有两种存放方式存放在应用程序集的配置文件中,对于Web应用程序则存放在Web.config中.这种方式必须指定配置节的处理程序(类);存放在一个单独的xml文件中,使用这种方式我们必须在程序中显式的加载配置文件,本文后面有详细说明.此方式有一个优点,就是在多数据库的情况下,可以用不同的配置文件与各个数据库进行对应.配置内容先来看看配置内容,下列是一个简单的配置例子:连接提供者,取值必须是实现了IConnectionProvider接口的类的全名,当前版本只能取值NHibernate.Connection.DriverConnectionProvider.数据库方言,取值必须是继承之Dialect的类的全名,最常用的就是NHibernate.Dialect.MsSql2000Dialect了吧,谁让它是M$的了.数据驱动类,取值必须是实现了IDriver接口的类的全名,常用的选择有NHibernate.Driver.SqlClientDriver,NHibernate.Driver.OleDbDriver等,不过现在又多了ByteFXDataDriver(访问MySQL).连接字符串,取值要与driver_class指定的数据驱动类对应.配置节处理程序因为NH的配置信息为自定义配置节,所以必须指定配置节处理程序,NH的配置内容采用key/value形式,这和预定义配置节appSettings是一样的,我们只要用.net内置的配置节处理程序就可以处理NH的配置内容了,这个处理key/value形式的类就是NameValueSetionHandler.nhibernate配置节的声明如下:注意Version的值对于不同的.netframework版本取值也可能不一样.在nh中,Environment类用于读取配置信息,代码如下//***Environment.cs-65行***staticEnvironment(){NameValueCollectionprops=System.Configuration.ConfigurationSettings.GetConfig(nhibernate)asNameValueCollection;if(props==null){return;}foreach(stringkeyinprops.Keys){properties[key]=props[key];}}这是一个静态构造函数,在静态成员首次调用时执行.配置信息放在properties集合中.//***Environment.cs-90行***publicstaticIDictionaryProperties{get{IDictionarycopy=newHashtable(properties.Count);foreach(DictionaryEntrydeinproperties){copy[de.Key]=de.Value;}returncopy;}}Properties属性用于访问配置信息,注意这里并没有直接返回properties,而是复制了一个集合用于返回.曾有网友问为什么不是直接返回properties可能的原因是如果返回properties(即引用)话,那么配置信息将是共享的,如果在程序中修改了properties,那么将影响到其它地方.另外Environment类中还定义了一些属性名称常数.在程序中操作配置信息除了在配置文件中指定nh的配置信息外,nh还允许我们在程序中操作配置信息,这对于一些敏感的数据,如数据库连接串,提供了一种安全的操作方法(可以在程序中加入连接串属性,而不用将其存储在配置文件中).Configuration类提供提供两个方法和一个属性用于操作配置信息.//***Configuration.cs-637行***publicConfigurationAddProperties(IDictionaryproperties){foreach(DictionaryEntrydeinproperties){this.properties.Add(de.Key,de.Value);}returnthis;}将一个数据字典对象加入到配置属性中.//***Configuration.cs-646行***publicConfigurationSetProperty(stringname,stringvalue){properties[name]=value;returnthis;}设置指定的属性的值,name应使用Environment类中定义的那些属性名称常数.//***Configuration.cs-625行***publicIDictionaryProperties{get{returnproperties;}set{this.properties=value;}}这个就不用多说的吧,用dotNet的人都知道.有了Properties,想干啥就干啥吧:-)NHibernate源码分析之一续:对象映射1.持久对象映射文件关于持久对象映射文件,这里就不多说了,可参考nhibernate的例子和文档.在nhibernate源代码的根目录里有一个nhibernate-mapping-2.0.xsd文档,这个文档是nhibernate用来对映射文件进行验证的,我们也可以借助相关软件用这个文档来验证映射文件的有效性.2.映射信息的读取通过Configuration类,可以用多种方式读取映射信息,一些以Add开头的方法就是用来加入映射信息的,这些方法最终将调用Add(XmlDocumentdoc).//**Configuration.cs**privateHashtableclasses=newHashtable();classes集合用于存放所有的持久对象映射信息,它的Key为持久类的类型;Value为PermissionClass类的子类.privatevoidAdd(XmlDocumentdoc){try{Binder.dialect=Dialect.Dialect.GetDialect(properties);Binder.BindRoot(doc,CreateMappings());}catch(MappingExceptionme){log.Error(Couldnotcompilethemappingdocument,me);throwme;}//endtry/catch}AddDocument方法调用Binder的静态方法BindRoot来绑定持久类映射信息.