本文并不是去詳細(xì)的介紹如何使用NHibernate,而是通過一個簡單的例子來演示基于NHibernate的三層結(jié)構(gòu)應(yīng)用程序開發(fā)過程。關(guān)于NHibernate的有關(guān)文檔,DDL已經(jīng)做了漢化,但是由于英文文檔自身就不完善,所以漢化后也是不全。菩提樹在一篇《NHibernate學(xué)習(xí)之路》隨筆中談到了學(xué)習(xí)NHibernate遇到的困難,也希望大家把自己在使用NHibernate中的經(jīng)驗和心得能夠共享出來,與大家分享。另外我也是剛開始接觸NHiernate,有錯誤之處還請大家指點。
第一步:準(zhǔn)備數(shù)據(jù)表
在這里用一個最簡單的例子,有一張關(guān)于的用戶的表,有編號,姓名,密碼,Email地址和最后一次的登錄時間幾個字段。
Create Table Users(

LogonID varchar(20) Primary key,

Name varchar(40),

Password varchar(20),

EmailAddress varchar(40) ,

LastLogon datetime

)
第二步:創(chuàng)建需要被持久化的類
在.NET中創(chuàng)建一個NHibernateWebDemo.Model的工程,添加User實體類。
//User.cs

using System;

namespace NHibernateWebDemo.Model

  {

public class User

 {

public User()

 {

}

private string id;

private string userName;

private string password;

private string emailAddress;

private DateTime lastLogon;

public string Id

 {

 get { return id; }

 set { id = value; }

}

public string UserName

 {

 get { return userName; }

 set { userName = value; }

}

public string Password

 {

 get { return password; }

 set { password = value; }

}

public string EmailAddress

 {

 get { return emailAddress; }

 set { emailAddress = value; }

}

public DateTime LastLogon

 {

 get { return lastLogon; }

 set { lastLogon = value; }

}

}

}
第三步:創(chuàng)建持久化映射文件
該文件的命名為User.hbm.xml,并且與User.cs放在同一個目錄里。設(shè)置該文件的生成操作屬性為“嵌入的資源”,這一點要切記。另外,使用編號當(dāng)作主鍵,由用戶輸入,所以在映射文件中用assigned。
<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">

<class name="NHibernateWebDemo.Model.User, NHibernateWebDemo.Model" table="users">

<id name="Id" column="LogonId" type="String" length="20">

<generator class="assigned" />

</id>

<property name="UserName" column= "Name" type="String" length="40"/>

<property name="Password" type="String" length="20"/>

<property name="EmailAddress" type="String" length="40"/>

<property name="LastLogon" type="DateTime"/>

</class>

</hibernate-mapping>
第四步:進(jìn)行配置文件的設(shè)置
在配置文件中,我們要告訴NHibernate所使用的數(shù)據(jù)庫是什么,以及如何連接該數(shù)據(jù)庫。
<configSections>

<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />

</configSections>

<nhibernate>

<add key="hibernate.connection.provider"

value="NHibernate.Connection.DriverConnectionProvider"/>

<add key="hibernate.dialect"

value="NHibernate.Dialect.MsSql2000Dialect"/>

<add key="hibernate.connection.driver_class"

value="NHibernate.Driver.SqlClientDriver"/>

<add key="hibernate.connection.connection_string"

value="server=.;uid=sa;pwd=sa;database=test"/>

</nhibernate>
第五步:編寫數(shù)據(jù)訪問層的公用類
在這里,編寫了兩個公用的類,分別進(jìn)行Session的創(chuàng)建和實體的操作。在這兩個類中用單件模式,來限制Session的創(chuàng)建。為了做到與具體的應(yīng)用程序無關(guān),在這里把程序集的名稱作為參數(shù),傳遞給OpenSession()方法??梢园堰@兩個類單獨放在一個名為Common的工程下,這里先把它們放在DAL層中。這兩個類只是個人的一種寫法,大家可以自行去編寫。
//SessionFactory.cs

using System;

using System.Reflection;

using System.Data;

using NHibernate;

using NHibernate.Cfg;

using NHibernate.Tool.hbm2ddl;

namespace NHibernateWebDemo.DAL

  {

public class SessionFactory

 {

public SessionFactory()

 {


}

private static ISessionFactory sessions;

private static Configuration cfg;

static readonly object padlock = new object();

public static ISession OpenSession(string AssemblyName)

 {

if(sessions == null)

 {

lock(padlock)

 {

if(sessions == null)

 {

BuildSessionFactory(AssemblyName);

}

}

}

return sessions.OpenSession();

}

private static void BuildSessionFactory(string AssemblyName)

 {

cfg = new Configuration();

cfg.AddAssembly(AssemblyName);

sessions = cfg.BuildSessionFactory();

}

}

}
//EntityControl.cs

using System;

using System.Collections;

using NHibernate;


namespace NHibernateWebDemo.DAL

  {

public class EntityControl

 {

private static EntityControl entity;

private string _AssemblyName;

static readonly object padlock = new object();

public static EntityControl CreateEntityControl(string AssemblyName)

 {

if(entity == null)

 {

lock(padlock)

 {

if(entity == null)

 {

entity = new EntityControl();

entity._AssemblyName = AssemblyName;

}

}

}

return entity;

}

public void AddEntity(Object entity)

 {

ISession session = SessionFactory.OpenSession(_AssemblyName);

ITransaction transaction = session.BeginTransaction();

try

 {

session.Save(entity);

transaction.Commit();

}

catch(Exception ex)

 {

transaction.Rollback();

throw ex;

}

finally

 {

session.Close();

}

}

public void UpdateEntity(Object entity,Object key)

 {

ISession session = SessionFactory.OpenSession(_AssemblyName);

ITransaction transaction = session.BeginTransaction();

try

 {

session.Update(entity,key);

transaction.Commit();

}

catch(Exception ex)

 {

transaction.Rollback();

throw ex;

}

finally

 {

session.Close();

}

}

public void DeleteEntity(object entity)

 {

ISession session = SessionFactory.OpenSession(_AssemblyName);

ITransaction transaction = session.BeginTransaction();

try

 {

session.Delete(entity);

transaction.Commit();

}

catch(Exception ex)

 {

transaction.Rollback();

throw ex;

}

finally

 {

session.Close();

}

}

public IList GetEntities(string strHQL)

 {

IList lst;

ISession session = SessionFactory.OpenSession(_AssemblyName);

ITransaction transaction = session.BeginTransaction();


lst=session.Find(strHQL);

transaction.Commit();

session.Close();

return lst;

}

}

}
第六步:編寫數(shù)據(jù)訪問層
創(chuàng)建一個名為NHibernateWebDemo.DAL的工程,數(shù)據(jù)訪問層的代碼編寫非常簡單,在創(chuàng)建EntityControl的實例時,需要把Model的程序集名稱作為參數(shù)傳入,可以通過配置文件來避免程序集名稱的硬編碼。
//UserDAL.cs

using System;

using System.Collections;

using NHibernateWebDemo.Model;

namespace NHibernateWebDemo.DAL

  {

public class UserDAL

 {

private EntityControl control;

public UserDAL()

 {

control = EntityControl.CreateEntityControl("NHibernateWebDemo.Model");

}

public void AddUser(User user)

 {

control.AddEntity(user);

}

public void UpdateUser(User user,string Id)

 {

control.UpdateEntity(user,user.Id);

}

public void DeleteUser(User user)

 {

control.DeleteEntity(user);

}

public IList GetAllUsers(string strHQL)

 {

return control.GetEntities(strHQL);

}

}

}
第七步:編寫業(yè)務(wù)邏輯層
建立NHibernateWebDemo.BLL工程,為了簡單期間,在業(yè)務(wù)邏輯層中我沒有做任何的業(yè)務(wù)檢測。
//UserBLL.cs

using System;

using System.Collections;

using NHibernateWebDemo.DAL;

using NHibernateWebDemo.Model;

namespace NHibernateWebDemo.BLL

  {

public class UserBLL

 {

public void AddUser(User user)

 {

UserDAL dal = new UserDAL();

dal.AddUser(user);

}

public void UpdateUser(User user,string Id)

 {

UserDAL dal = new UserDAL();

dal.UpdateUser(user,Id);

}

public void DeleletUser(User user)

 {

UserDAL dal = new UserDAL();

dal.DeleteUser(user);

}

public IList GetAllUsers(string strHQL)

 {

UserDAL dal = new UserDAL();

return dal.GetAllUsers(strHQL);

}

}

}
第八步:實現(xiàn)用戶界面
用戶界面很簡單,這里就不給出代碼了,完成后的用戶界面:

完整代碼下載:/Files/Terrylee/NHibernateWebDemo.rar
Feedback
# re: 基于NHibernate的三層結(jié)構(gòu)應(yīng)用程序開發(fā)初步 回復(fù)
2006-02-16 18:11 by
這個,張老三寫的那幾篇更好,而且他的DOMAINOBJECTCONTROL寫的很棒 提幾個小建議: 1,業(yè)務(wù)邏輯層是不是該進(jìn)行一下業(yè)務(wù)邏輯的判斷呀 例如,ADD一個USER前,是不是該判斷是下該USER是不是存在 USER的各個屬性值,是否符合邏輯 這些都不做的話,這些工作放在哪兒呢? DAL僅負(fù)責(zé)串行化數(shù)據(jù)以及事務(wù)處理,而BAL剛負(fù)責(zé)業(yè)務(wù)邏輯,所謂業(yè)務(wù)邏輯,應(yīng)該包含這些吧 最后,一個建議,不要把校驗的任務(wù)交給DBMS,不要依賴于它的約束等,雖然你寫了約束等,但是,不要等在串行化時,才檢查數(shù)據(jù)有效性
|