开始使用NHibernate
好久没有写日志了,今天有些时间,谢谢.NET中的持久化框架技术NHibernate
我们很多人都用过Java的持久化框架技术Hibernate,实现ORM机制。在.NET中同样可以实现相同操作,采用类似于Hibernate的NHibernate。本文章主要介绍NHibernate的使用,在后续的文章中详细的深入。
NHibernate几乎和Java中的Hibernate一样,无论是会话工厂、会话、事务处理、多表映射等等,都是差不多的。
首先需要准备NHIbernate的必备组件,可以到http://downloads.sourceforge.net/nhibernate/NHibernate-1.2.0.CR1.msi?modtime=1172161735&big_mirror=0 下载。然后安装。
可以安装到你想要安装的目录中,其中包含bin、doc、src三个目录
其中bin目录包含.NET1.1和.NET2.0的必备组件;doc包含帮助文档,src当然是源代码了
在此我用Viso2003进行演示,使用.NET1.1中的必备组件
首先建立一个ASP.NET工程,在此命名为FirstUser
添加引用,引用.NET1.1必备组件的NHibernate.dll
修改其中的web.config配置文件。在此web.config配置文件类似于hibernate.cfg.xml,包含SessionFactory的配置信息。在NHibernate中可以采用web.xml或者hibernate.cfg.xml作为hibernate的默认配置文件。在此采用web.config。
修改内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"
/>
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.connection_string">Server=127.0.0.1;Uid=sa;Pwd=;Database=BookDB</property>
<mapping assembly="FirstUser"/>
</session-factory>
</hibernate-configuration>
<system.web>
.................................
</system.web>
</configuration>
其中声明配置节hibernate-configuration,类型为NHibernate.Cfg.ConfigurationSectionHandler, NHibernate。这样NHibernate可以读取hibernate-configuration配置节中的配置信息。
hibernate-configuration的配置信息配置sessionFactory,当然是配置数据库的连接等信息。在此增加三个属性节点,分别配置“方言”、“连接提供者”、“连接字符串”。由于在此数据库采用MSSQL2000,所以不用提供数据库驱动(.NET自带),如果是其他数据库,例如MSSQL,需要配置驱动信息。
最后包含自节点<mapping assembly="FirstUser"/>指明对程序集(当前的工程)FirstUser下的实体类进行映射。
好了,现在可以开始写持久化类了。在Java中卫POJO类,在.NET中称为POCO类(Plain Ordinary CLR Objects)。此类和数据库中的表产生映射关系。在数据库中建立UserInfo表,包含三个字段,分别为userid,username,userpass
其中userid为自增类型(identity(1,1)),其余为varchar类型。
建立的持久化类包含在子命名空间poco中(当然也可以直接放在根命名空间FirstUser中,在此进行有效的组织)。
using System;
namespace FirstUser.poco
{
/// <summary>
/// UserInfo 的摘要说明。
/// </summary>
public class UserInfo
{
private int id;
public virtual int Id
{
get{ return this.id;}
set{ this.id=value;}
}
private string username;
public virtual string Username
{
get{ return this.username;}
set{ this.username=value;}
}
private string userpass;
public virtual string Userpass
{
get{ return this.userpass;}
set{ this.userpass=value;}
}
public UserInfo()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
}
}
其中注意:主键数据成员名称为id,而且所有的属性为virtual(虚属性)形式
下面再工程下建立映射文件(hbm.xml)。名称为UserInfo.hbm.xml。内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="FirstUser.poco" assembly="FirstUser">
<class name="UserInfo" table="UserInfo">
<id name="Id">
<column name="userid"/>
<generator class="identity"/>
</id>
<property name="Username">
<column name="username"/>
</property>
<property name="Userpass">
<column name="userpass"/>
</property>
</class>
</hibernate-mapping>
其中红体部分指明映射的类包含在poco的子命名空间中,兰体部分指明映射的类在FirstUser程序集中。映射方式和Java的Hibernate一样(自己理解吧)。
众所周知,在采用Hibernate做持久化操作的时候,需要建立会话工程。会话工程会根据配置文件(web.config)中的配置产生,以便知道如何进行数据库连接。会话工厂产生会话(Session),会话负责完成持久化的具体操作。
会话工厂一般只需要产生一个,然后多次使用。除非同时连接不同的数据库。所有可以建立一个工具类得到会话工厂。此工具类为工厂类型是,负责产生会话工程,并由使用者取得,进而产生会话。
在此使用单态模式,保证会话工厂的实例唯一。
using System;
using System.Web;
using NHibernate;
using NHibernate.Cfg;
namespace FirstUser.rule
{
/// <summary>
/// NHibernateHelper 的摘要说明。
/// </summary>
public sealed class NHibernateHelper
{
/// <summary>
/// CurrentSessionKey为保存在http上下文中的当前会话的键值
/// </summary>
private const string CurrentSessionKey="nhibernate.current_session";
private static readonly ISessionFactory sessionFactory;
/// <summary>
/// 通过web.config配置文件建立会话工厂,此会话工厂为单态新式
/// </summary>
static NHibernateHelper()
{
sessionFactory = new Configuration().Configure().BuildSessionFactory();
}
/// <summary>
/// 得到Http上下文保存的会话实例。如果会话不存在,则创建,并保存到Http上下文中
/// </summary>
/// <returns></returns>
public static ISession GetCurrentSession(){
HttpContext context = HttpContext.Current;
ISession currentSession=context.Items[CurrentSessionKey] as ISession;
if(currentSession==null)
{
currentSession = sessionFactory.OpenSession();
context.Items[CurrentSessionKey] = currentSession;
}
return currentSession;
}
/// <summary>
/// 关闭当前会话,并将会话从Http上下文中清除
/// </summary>
public static void CloseSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if(currentSession==null)
{
return ;
}
currentSession.Close();
context.Items.Remove(CurrentSessionKey);
}
/// <summary>
/// 关闭会话工厂
/// </summary>
public static void CloseSessionFactory()
{
if(sessionFactory!=null)
sessionFactory.Close();
}
}
}
上述工具类参考了NHibernate的帮助文档。为了便于组织,将上述的类放入rule子命名空间中
开始进行测试了。
建立一个普通的aspx页面,放入两个TextBox,分别用来收集用户输入的用户名和密码。放入一个Button,在click事件中编写如下代码,保存输入的用户名和密码。
ISession session = NHibernateHelper.GetCurrentSession();
ITransaction tx = session.BeginTransaction();
UserInfo user= new UserInfo();
user.Username = txtUsername.Text.Trim();
user.Userpass = txtUserpass.Text.Trim();
session.Save(user);
tx.Commit();
NHibernateHelper.CloseSession();
类中需要引用如下的命名空间,以便实现NHibernate操作
using NHibernate;
using NHibernate.Cfg;
运行测试,看看是否将数据保存到了数据库中