NHibernate学习一入门
看过不少NHibernate入门的介绍文章,由于版本原因和步骤省略,依葫芦画瓢,却不能写入数据,最后终于调通,特写随笔记下。
环境: vs2008 sp1 + sqlserver 2005 + NHibernate-2.1.2.GA-bin
下载: NHibernate-2.1.2.GA-bin下载地址http://downloads.sourceforge.net/project/nhibernate/NHibernate/2.1.2GA/NHibernate-2.1.2.GA-bin.zip
准备: 先在数据库 建立 database: Nhibernate 建立 table: Person
USE [Nhibernate]
GO
/****** 对象: Table [dbo].[Person] 脚本日期: 05/09/2010 18:17:53 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Person](
[PersonId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
[Age] [int] NULL,
[Birthday] [datetime] NULL,
[Address] [nvarchar](200) COLLATE Chinese_PRC_CI_AS NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[PersonId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
说明:以上分别是表结构与项目结构,与lib文件夹列表,在项目里单独开一个lib文件,方便项目引用。他们来自NHibernate-2.1.2.GA-bin\Required_Bins 与 NHibernate-2.1.2.GA-bin\Required_For_LazyLoading\Castle
步骤:
一 先建立解决方案 NhibernatePractice,建立3个类库与1个 aspnet 站点
二 建立模型: NHDemoDomain
建立实体类 Person:
namespace NHDemoDomain.Entities
{
public class Person
{
// 注意:virtual 声明,否则会报错
public virtual int PersonId { get; set; }
public virtual string Name { get; set; }
public virtual int Age { get; set; }
public virtual DateTime Birthday { get; set; }
public virtual string Address { get; set; }
}
}
建立实体类 person的 关系映射 xml : Person.hbm.xmls
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHDemoDomain" namespace="NHDemoDomain.Entities">
<class name="Person" table="Person">
<id name="PersonId" column="PersonId">
<generator class="native"></generator>
</id>
<property name="Name" column="Name"/>
<property name="Age" column="Age"/>
<property name="Birthday" column="Birthday"/>
<property name="Address" column="Address"/>
</class>
</hibernate-mapping>
请注意: assembly和namespace 因为我有文件夹所以是不同的,请根据自己实际情况指定相应名称。
下面配置除了 id 特殊点,其他都是属性,column 对应 数据库的列,table对应数据库的表
class="native" 按数据库组件处理。
再这一层特别注意保留字,我开始因为建了个User,结果因为保留字而一直报错,不能保存。
特别注意:Person.hbm.xmls 在vs里按右键属性,进行设置,“复制到输出目录”,选择“始终复制”,“生成的操作”,选择“嵌入的资源”,否则会报错,找不到指定文件。
二 建立NHDemoNHDAL,数据处理。
引用前面提到的 lib 文件夹里的所有dll,建立NHibernateHelper 类
using NHibernate;
using NHibernate.Cfg;
namespace NHDemoNHDAL
{
public sealed class NHibernateHelper
{
private static ISessionFactory sessionFactory;
static NHibernateHelper()
{
sessionFactory = new Configuration().Configure().BuildSessionFactory();
}
public static ISession GetSession()
{
return sessionFactory.OpenSession();
}
}
}
记得添加对 NHibernate 的引用,sessionFactory = new Configuration().Configure().BuildSessionFactory();
新版本不再有对 hibernate.cfg.xml 文件指定,此文件设置好了,就把它复制到 web 站点的 bin 目录下,NH会自动去找这个文件,配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.connection_string">
server=.;uid=sa;pwd=;database=Nhibernate;
</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
</property>
<mapping assembly="NHDemoDomain"/>
</session-factory>
</hibernate-configuration>
注意: 新版必须设置 factory_class ,我这里引用的是Castle,可根据需要引用另外2个工厂。
但必须吧NHibernate-2.1.2.GA-bin\Required_For_LazyLoading你所引用的相应工厂里的dll引用进来。
NHibernate.Dialect.MsSql2005Dialect,表示我用的是sqlserver2005数据库,采用此数据库方言。大家可根据实际情况修改自己的数据库方言。
当然,你也可以选择用web.config来进行统一设置:
<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.MsSql2005Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.connection_string">
server=.;uid=sa;pwd=;database=Nhibernate;
</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
</property>
<mapping assembly="NHDemoDomain"/>
</session-factory>
</hibernate-configuration>
在 <appSettings/> 前面加上上面的配置代码。
建立 PersonHelper,person数据处理类:
using NHDemoDomain.Entities;
using NHibernate;
using NHibernate.Cfg;
namespace NHDemoNHDAL
{
public class PersonHelper
{
static PersonHelper()
{
}
public static int Insert(Person pson)
{
int id = 0;
ISession session = NHibernateHelper.GetSession();
ITransaction ts = session.BeginTransaction();
session.Save(pson);
ts.Commit();
session.Close();
id = pson.PersonId;
return id;
}
}
}
注意添加引用,domain 和 NH 引用,这个类就是NH处理数据的核心,建立 session 通道,对数据进行保存插入数据库,启用了事物BeginTransaction,保存完毕后 NH会自动跟新 Person,所以id = pson.PersonId; 可以获取自动生成ID。
三 建立 NHDemonLogic 逻辑处理
建立 PersonHandle 类:
using NHDemoNHDAL;
using NHDemoDomain.Entities;
namespace NHDemonLogic
{
public class PersonHandle
{
private static log4net.ILog ilog = null;
static PersonHandle()
{
ilog = log4net.LogManager.GetLogger(typeof(PersonHandle));
}
/// <summary>
/// 插入数据
/// </summary>
/// <param name="pName"></param>
/// <param name="pAge"></param>
/// <param name="pBirthday"></param>
/// <param name="pAddress"></param>
/// <returns></returns>
public static int Insert(string pName, string pAge, string pBirthday, string pAddress)
{
int id = 0;
try
{
int age = Convert.ToInt32(pAge);
DateTime birthday = Convert.ToDateTime(pBirthday);
Person ps = SetPesson(pName, age, birthday, pAddress);
id=PersonHelper.Insert(ps);
}catch(Exception ex){
ilog.Error("error:",ex);
}
return id;
}
/// <summary>
/// 组装 person
/// </summary>
/// <param name="name"></param>
/// <param name="age"></param>
/// <param name="birthday"></param>
/// <param name="address"></param>
/// <returns></returns>
public static Person SetPesson(string name,int age,DateTime birthday,string address)
{
Person ps = new Person();
ps.Name = name;
ps.Age = age;
ps.Birthday = birthday;
ps.Address = address;
return ps;
}
}
}
这个类,主要负责从web 抓到的文本数据,进行类型转换,组装 person 然后交给PersonHelper 去处理。监控异常,写日志。
四: 完善 NHDemoWeb
NH的配置前面已经说了,下面主要是吧 log4net 配置加进去:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
加在 <configSections>里。
<log4net>
<appender name="NHibernateFileLog" type="log4net.Appender.RollingFileAppender">
<file value="Logs/nhibernate.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{yyyy-MM-dd HH:mm} %-5p %c [%L] - %m%n" />
</layout>
</appender>
<appender name="GeneralLog" type="log4net.Appender.RollingFileAppender">
<file value="Logs/general.txt" />
<appendToFile value="true" />
<maximumFileSize value="100KB" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{yyyy-MM-dd HH:mm} [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="LogicLog" type="log4net.Appender.RollingFileAppender">
<file value="Logs/logic.txt" />
<appendToFile value="true" />
<maximumFileSize value="100KB" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{yyyy-MM-dd HH:mm} %-5p %c [%L] - %m%n" />
</layout>
</appender>
<!-- levels: DEBUG, INFO, WARN, ERROR, FATAL -->
<root>
<level value="DEBUG"/>
<appender-ref ref="GeneralLog" />
</root>
<logger name="NHibernate" additivity="false">
<level value="WARN"/>
<appender-ref ref="NHibernateFileLog"/>
</logger>
<logger name="NHDemonLogic" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="LogicLog"/>
</logger>
</log4net>
加在 <appSettings/> 前面,logger name="NHibernate" 是针对 命名空间为NHibernate的日志,logger name="NHDemonLogic" 主要记录业务逻辑日志。
增加 Global.asax 文件,对log4net 初始化。
void Application_Start(object sender, EventArgs e)
{
//在应用程序启动时运行的代码
log4net.Config.DOMConfigurator.Configure(); // 初始化日志配置
}
前端页面控件如下:
后端页面代码如下:
public partial class _Default : System.Web.UI.Page
{
log4net.ILog ilog = null;//
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
ilog = log4net.LogManager.GetLogger(typeof(_Default));
}
}
protected void btn_insert_Click(object sender, EventArgs e)
{
string name = tb_name.Text;
string age = tb_age.Text;
string birthday = tb_birthday.Text; //DateTime.Now.ToString();
string address = tb_address.Text;
int id = 0;
try
{
id = PersonHandle.Insert(name, age, birthday, address);
//ilog.Info("id=" + id.ToString() + "插入成功");
}
catch(Exception ex)
{
ilog.Error("insert error", ex);
}
if (id > 0)
lb_insertResult.Text = "id=" + id.ToString() + "插入成功";
else
lb_insertResult.Text = "插入失败";
}
}
简单的获取数据传参。
下面附上源码,以供参考: