对ORM(Object/Relation Mapping)技术了解的都知道,NHibernate是基于.Net的一种数据持久化的框架。之前在Java里了解过Hibernate框架,但平时开发还是.Net用得比较多,而且目前面向对象和关系型数据库的开发应用仍然是主流,所以觉得有必要去了解学习NHibernate这个优秀的ORM框架。
一、类库
在我的这个NHibernate2.1.2.GA版的程序事例中,是使用VS2005工具开发的,引用NHibernate的相关类库文件如下:
| 名称 | 功能 |
|---|---|
| NHibernate.dll | NHibernate核心类库 |
| Iesi.Collections.dll | 提供集合运算功能 |
| NHibernate.ByteCode.Castle.dll | 使用Castle动态代理 |
| Castle.Core.dll | Castle代理核心类库 |
| Castle.DynamicProxy2.dll | Castle动态代理 |
| Antlr3.Runtime.dll | 语法分析和词法分析(未使用) |
二、配置
NHibernate可以有几种加载配置的方式:Web.Config/App.Config、hibernate.cfg.xml、编码指定配置文件。因为在我的这个事例是Asp.Net的NHibernate网站程序,所以在Web.Config的configSections下增加section节点来配置NHibernate。也可以独立出hibernate.cfg.xml配置文件,放在网站Bin目录下,使用如下方式实例化:
Configuration config = new Configuration().Configure();
NHibernate默认会在目录下自动查找hibernate.cfg.xml配置文件。
如下为我的Web.Config配置文件内容:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<appSettings/>
<connectionStrings/>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="NHibernateDemo">
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Data Source=.\SQL2005;Initial Catalog=Jonllen;
Integrated Security=True;Pooling=False
</property>
<property name="adonet.batch_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="use_outer_join">true</property>
<property name="command_timeout">10</property>
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.Castle.ProxyFactoryFactory,
NHibernate.ByteCode.Castle
</property>
<mapping assembly="NHibernateDemo.Domain"/>
</session-factory>
</hibernate-configuration>
<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>
<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>
</log4net>
<system.web>
<compilation debug="true">
<assemblies>
</assemblies>
</compilation>
<authentication mode="Forms"/>
</system.web>
</configuration>
三、映射
NHibernate提供了几种方式的实体关系映射,比较灵活的是使用xml文件进行映射,将实体类与数据表的关系描述配置。使用这种方式要指定NHibernate配置session-factory中mapping的assembly实体程序集,*.hbm.xml实体映射文件属性的生成操作都要设置为嵌入的资源,因为NHibernate是通过查找程序集中的资源文件映射实体的。
如下为我的User.hbm.xml映射文件内容:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemo.Domain"
namespace="NHibernateDemo.Domain.Entities">
<class name ="User" table="bl_user" >
<id name="UserId" column ="userId">
<generator class ="native"/>
</id>
<property name ="Username"/>
<property name ="Password"/>
<property name ="LoginTimes"/>
<property name ="RegisterDate"/>
<property name ="UserStatus"/>
<property name ="TemplateDisplay"/>
</class>
</hibernate-mapping>
NHibernate也提供在编码时自定义映射方式,如使用Fluent在创建ISessionFactory时动态添加要映射的程序集。另外,我曾经在Hibernate中可以使用注解方式,即直接在实体类上添加注释来映射,我想在.Net中NHibernate应该也可以使用元数据进行实体映射。
四、延迟加载
NHibernate2.1版本提供三种3种框架动态代理,分别为Castle框架、LinFu框架、Spring.Net框架,以实现延迟加载功能。在我的这个NHibernate事例中是使用的Castle框架,它要求持久化类不是sealed密封类,且其公共方法、属性和事件声明必须为virtual,否则将出现如下错误:
The following types may not be used as proxies:NHibernateDemo.Domain.Entities.User: method get_UserId should be 'public/protected virtual' or 'protected internal virtual'
如果非得每个实体属性都要为virtual好象有点强人所难,于是我把User.hbm.xml中class的lazy="false",改为默认不使用延迟加载就没问题了。如果能正常使用延迟加载功能固然是好,但一般取数据实体里的属性一般都会是确定的,实在不行也可以在业务逻辑层里再手动填充实体属性,所以也不一定就要使用延迟加载。
目前.Net实现动态代理功能似乎都对现有的有侵入性,不是要求继承类就是有其它的实现条件。而之所以要有virtual这个条件是因为创建代理对象需要override实体类型的方法属性,以实现对方法属性的拦截处理,植入执行前和执行后的逻辑,以实现延迟加载的功能。而在Java中则专门提供了InvocationHandler代理接口,并且所有方法默认都可以Override,因此实现Aop动态代理就很简单。
本事例VS2005工程源代码下载:NHibernateDemo


- 引用
1楼 青岛红酒 2011-06-01 10:18:00- 引用
2楼 金顺道物流 2011-06-01 10:18:27