最近因为项目的需要,数据层想换成NHibernate,我以前在做JAVA时虽曾接触过Hibernate,但好些年过去了,做第一个实例居然费了我好些精力,现把成功的例子贴出来。
1、建立数据表和实体对象
数据库是用的MSSQL2008,建表语句就不贴了,总共就3个字段。下面是实体对象代码
using System;
namespace Example.Domain
{
public class Item
{
private int id;
private decimal price;
private string description;
public virtual int Id
{
get { return id; }
set { id = value; }
}
public virtual decimal Price
{
get { return price; }
set { price = value; }
}
public virtual string Description
{
get { return description; }
set { description = value; }
}
}
}
2、在Item对象的同一项目(同一目录)下新建一个与实体对象同名的XML文件,以“hbm.xml”为扩展名。如:Item.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Example.Domain"
namespace="Example.Domain">
<!--
Class has to be non-lazy because Medium Trust Level restrictions
prevent proxy generation from working.
-->
<class name="Item" table="Item" lazy="false">
<id name="Id">
<generator class="native" />
</id>
<property name="Price" />
<property name="Description" />
</class>
</hibernate-mapping>
这里重点说一下 assembly 和 namespace属性。
assembly:集合的名称,如果在一个项目下有许多个实体对象,我们只需要指定这个属性,并在web.config中加入 如: “<mapping assembly="Example.Domain"/>”就行了。
namespace:命名空间,如果设定了这个属性,class的 name只要指定与实体对象同名就行了。
还有要特别注意的是:XML文件的默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,因为NHibernate是通过查找程序集中的资源文件映射实体。这样在生成类库DLL文件时,这个XML文件才会打包进去,同时名称要自动修改为“Example.Domain.Item.hbm.xml”。
3、web.config中进行配置
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" requirePermission="false"/>
<!-- Important under Medium Trust -->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false"/>
<!-- Important under Medium Trust -->
</configSections>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true">
</compilation>
<authentication mode="Windows"/>
<pages enableViewState="false" enableViewStateMac="false">
</pages>
<httpModules>
<add name="CurrentSessionModule" type="NHibernate.Example.Web.CurrentSessionModule"/>
</httpModules>
</system.web>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<bytecode-provider type="null"/>
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider, NHibernate</property>
<property name="connection.connection_string">
Data Source=PC-20110811NRNE\SQLEXPRESS;initial catalog=Northwind;Integrated Security=true;User ID=user1;Password=pwd1
</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="current_session_context_class">managed_web</property>
<property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory,NHibernate</property>
<mapping assembly="Example.Domain"/>
</session-factory>
</hibernate-configuration>
<log4net>
<!-- Define some output appenders -->
<appender name="trace" type="log4net.Appender.TraceAppender, log4net">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<appender name="console" type="log4net.Appender.ConsoleAppender, log4net">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<root>
<priority value="WARN"/>
<appender-ref ref="trace"/>
</root>
</log4net>
</configuration>
标红色背景的是要特别注意的地方。3.3.2版本的测试通过,从网上搜集的先前版本的例子都不正常了。
4、ISeesion调用代码
using System.Web;
using System.Web.Hosting;
using NHibernate.Cfg;
using Example.Domain;
namespace NHibernate.Example.Web
{
public class ExampleApplication : HttpApplication
{
public static readonly Configuration Configuration;
public static readonly ISessionFactory SessionFactory;
static ExampleApplication()
{
log4net.Config.XmlConfigurator.Configure();
Configuration = new Configuration();
string nhConfigPath = HostingEnvironment.MapPath("~/App_Data/hibernate.cfg.xml");
if (File.Exists(nhConfigPath))
{
Configuration.Configure(nhConfigPath);
}
SessionFactory = Configuration.Configure().BuildSessionFactory();
}
public static ISession GetCurrentSession()
{
return SessionFactory.GetCurrentSession();
}
}
}
还有个类:
using System;
using System.Web;
using NHibernate.Context;
namespace NHibernate.Example.Web
{
public class CurrentSessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
context.EndRequest += new EventHandler(Application_EndRequest);
}
public void Dispose()
{
}
private void Application_BeginRequest(object sender, EventArgs e)
{
ManagedWebSessionContext.Bind(HttpContext.Current, ExampleApplication.SessionFactory.OpenSession());
}
private void Application_EndRequest(object sender, EventArgs e)
{
ISession session = ManagedWebSessionContext.Unbind(HttpContext.Current, ExampleApplication.SessionFactory);
if (session.Transaction.IsActive)
{
session.Transaction.Rollback();
}
if (session != null)
{
session.Close();
}
}
}
}
5、数据层封装类
using System;
using System.Collections.Generic;
using Example.Domain;
namespace NHibernate.Example.Web.Persistence
{
public class ItemList
{
public IList<Item> GetAllItems()
{
return ExampleApplication.GetCurrentSession().CreateQuery("from Item").List<Item>();
}
public void UpdateItem(Item item)
{
ExampleApplication.GetCurrentSession().SaveOrUpdateCopy(item);
}
public void DeleteItem(Item item)
{
ISession session = ExampleApplication.GetCurrentSession();
session.Delete(session.Load(typeof(Item), item.Id));
}
public void InsertItem(Item item)
{
ExampleApplication.GetCurrentSession().Save(item);
}
}
}
以上代码在我本机测试通过。