看过不少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
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:
{
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
< 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.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会自动去找这个文件,配置如下:
< 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来进行统一设置:
这句加到 <configSections>里面:
< 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 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 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>里。
< 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 初始化。
{
// 在应用程序启动时运行的代码
log4net.Config.DOMConfigurator.Configure(); // 初始化日志配置
}
前端页面控件如下:
后端页面代码如下:
{
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 = " 插入失败 " ;
}
}
简单的获取数据传参。
下面附上源码,以供参考: