NHibernate學習手記(1) - 對象的簡單CRUD操作

你是否正在爲編寫和維護冗長和複雜的SQL語句而苦惱?

你是否厭倦了繼續以面向過程的開發方式,而想開始嘗試以面向對象的方式去思考?

你是否想跳出重複編寫SQL語句的囹圇,而想更加專注於實現用戶需求的邏輯實現?

...

和許多開發人員一樣,我非常反感(甚至是恐懼)sql語句,這種當初設計用來和數據庫進行會話的語言,想不到現在被發揚光大到可以用來編寫業務邏輯(通過任意複雜的組合)。但我們完全可以以對象的方式來思考數據庫編程,通過採用ORM(Object-Relation Mapping),把我們從繁雜的Sql語句編寫工作中解脫出來,從而引導我們以對象的方式進行開發。

於是我最近打算學習NHibernate(簡稱NH),並將陸續在blog上發表學習的總結,希望能夠和各位多多交流。

主要內容

1、事先的準備工作

2、編寫帖子(Post)的實體類

3、編寫NH所需要的配置文件

4、使用NH進行對象的CRUD操作

5、淺談Rich Domain Model

 

一、準備工作

首先,我們在數據庫NHTrial中新建一數據表nh_posts,用於存儲帖子數據

CREATE TABLE [dbo].[nh_posts] ( [PostID] [uniqueidentifier] NOT NULL , [Title] [varchar] (255) COLLATE Chinese_PRC_CI_AS NOT NULL , [Content] [text] COLLATE Chinese_PRC_CI_AS NOT NULL , [Creator] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL , [CreateDate] [datetime] NOT NULL , [LastUpdateDate] [datetime] NULL , [LastUpdator] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

 

二、編寫Post實體類

新建工程NHClass,添加類Post.cs,並編寫代碼如下:

using System; using System.Collections; namespace NHClass { /// /// Post 貼子類 /// /// 創 建 人: Aero /// 創建日期: 2006-3-9 /// 修 改 人: /// 修改日期: /// 修改內容: /// 版 本: public class Post { #region 數據成員定義 private Guid postId; private string title; private string content; private string creator; private DateTime createDate = System.DateTime.Now; private string lastUpdator; private DateTime lastUpdateDate = System.DateTime.Now; #endregion #region 屬性定義 public Guid PostID { get { return this.postId; } set { this.postId = value; } } public string Title { get { return this.title; } set { this.title = value; } } public string Content { get { return this.content; } set { this.content = value; } } public string Creator { get { return this.creator; } set { this.creator = value; } } public DateTime CreateDate { get { return this.createDate; } set { this.createDate = value; } } public string LastUpdator { get { return this.lastUpdator; } set { this.lastUpdator = value; } } public DateTime LastUpdateDate { get { return this.lastUpdateDate; } set { this.lastUpdateDate = value; } } #endregion #region 構造函數 /// /// 默認無參構造函數 /// /// 創 建 人: Aero /// 創建日期: 2006-3-9 /// 修 改 人: /// 修改日期: /// 修改內容: public Post() { // // TODO: 在此處添加構造函數邏輯 // } #endregion } }

NH通過O/R Mapping,把關係數據映射爲實體對象(字段映射爲實體的屬性),讓我們在開發只需直接操縱對象。

 

三、編寫NHibernate需要的配置文件

NH實現O/R Mapping當然不是通過某種神奇的方式,需要我們編寫配置文件來告訴它該如何進行對象映射,並且已哪種方式來運行NH,需要映射的是什麼類型的數據庫等。

1、編寫用於O/R Mapping的配置文件。

NHibernate提供多種編寫配置文件的方式,本文只討論最簡單的方式,即爲每一個實體類編寫一個配置文件。在工程NHClass中新建文件Post.hbm.xml,把該文件的屬性設爲"嵌入資源",並輸入以下內容:

<xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"> <class name="NHClass.Post, NHClass" table="nh_posts"> <id name="PostID" column="PostID" type="Guid"> <generator class="assigned" /> id> <property name="Title" column="Title" type="String" length="255"/> <property name="Content" column="Content" type="String" /> <property name="Creator" column="Creator" type="String" length="50"/> <property name="CreateDate" column="CreateDate" type="DateTime"/> <property name="LastUpdator" column="LastUpdator" type="String" length="50"/> <property name="LastUpdateDate" column="LastUpdateDate" type="DateTime"/> </class> </hibernate-mapping>

下面簡單說明一下該配置文件:

1)class: name屬性指示了Post實體類的類名和所在的Assebmly的名稱,NH將通過反射的方式找到所指示的實體類,關於.Net的反射的說明,請參考MSDN; table屬性指示了該實體所對應的數據表的表名

2)property: 指示實體屬性和數據列的如何映射。name爲實體的屬性名稱,實體的該屬性可以爲public/private/protected,甚至是internal;column指示了該屬性對應的數據列,若實體屬性名稱和數據列名稱相同(忽視大小寫),可以省略;type指示了實體屬性的.Net數據類型,可以省略,NH可以自動轉換;length只是對string類型的屬性適用,指示了字符串的最大長度。

3)id: 指示主鍵。NH支持自動生成主鍵、數據庫生成主鍵和手工賦值三種方式,我們這裏手工賦值的方式,設定generator的class="assigned"。

2、修改app.config或web.config配置NHibernate的屬性。

在app.config或web.config文件中添加以下內容:

<configSections> <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.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=localhost;uid=sa;password=sa;database=NHTrial" /> nhibernate>

該配置信息指定了NH的運行時、所使用的數據庫驅動程序和數據庫連接字符串等信息,也可在運行的時候賦值。

 

四、使用NHibernate進行對象的CRUD操作

相信大家都迫不及待了把,現在讓我們看看如何使用NH進行簡單的CRUD。請注意本文的用詞,我們討論的是對象的操作,不是過程化的sql調用!

1、添加Post對象

void AddPost() { // initialize the configuration Configuration cfg = new Configuration(); cfg.AddAssembly("NHClass");
   ISessionFactory factory = cfg.BuildSessionFactory();
    // start a session with the database // the ISession object represents a connection to your backend database
   ISession session = factory.OpenSession();     // the ITransaction object represents a NH Managed transaction // always start a transaction before u want to do something on the backend database ITransaction trans = session.BeginTransaction(); // initialize ur Post Post post = new Post(); post.PostID = Guid.NewGuid(); post.Title = "hello Nibernate"; post.Content = "foo test"; post.Creator = "foo"; post.LastUpdator = "bar"; post.CreateDate = System.DateTime.Now.Date; post.LastUpdateDate = System.DateTime.Now.Date; // store the new post session.Save(post); // commit the transaction trans.Commit(); // end the session session.Close(); }

沒錯,就是那麼簡單!打開和數據庫的會話,保存對象,最後關閉會話,一切都那麼自然。美中不足的是其中的cfg.AddAssembly("NHClass")表示註冊Post類所在的程序集,感覺很不優雅。

其他的操作都要用到ISessionFactory,爲了便於描述,我們先進行一次簡單的重構,Extract Method:

ISessionFactory _factory; ISessionFactory Factory { get { if (_factory == null) { // initialize the configuration Configuration cfg = new Configuration(); cfg.AddAssembly("NHClass"); // create a session object // the ISession object represents a connection to your backend database _factory = cfg.BuildSessionFactory(); }
      
         return _factory; } } void AddPost() { // start a session with the database // the ISession object represents a connection to your backend database ISession session = this.Factory.OpenSession(); // the ITransaction object represents a NH Managed transaction // always start a transaction before u want to do something on the backend database ITransaction trans = session.BeginTransaction(); // initialize ur Post Post post = new Post(); post.PostID = Guid.NewGuid(); post.Title = "hello Nibernate"; post.Content = "foo test"; post.Creator = "foo"; post.LastUpdator = "bar"; post.CreateDate = System.DateTime.Now.Date; post.LastUpdateDate = System.DateTime.Now.Date; // store the new post session.Save(post); // commit the transaction trans.Commit(); // end the session session.Close(); }

2、查詢帖子

先看看怎麼查詢全部的帖子

void ListAllPost() { Console.WriteLine("list all post in table nh_posts"); // start a session ISession session = this.Factory.OpenSession(); IList posts = session.CreateCriteria(typeof(Post)).List(); foreach (Post post in posts) { Console.WriteLine(post.PostID.ToString() + " : " + post.Title); } session.Close(); }

再看看怎麼查詢指定PostID的帖子

void ListPostById(Guid postId) { Console.WriteLine("list posts of the given id"); IList posts = null; // start a data session ISession session = this.Factory.OpenSession(); // get post of the given post id posts = session.CreateCriteria(typeof(Post)) .Add(Expression.Eq("PostID", postId)).List(); // close a session to the backend database session.Close(); foreach (Post post in posts) { Console.WriteLine(post.PostID.ToString() + " : " + post.Title); } }

查詢所有標題包含關鍵字的帖子對象,並以LastUpdateDate降序排列

void ListPostByTitle(string keyword) { Console.WriteLine("list posts that contains the given keyword in their title, sorted by last update date"); IList posts = null; // start a data session ISession session = this.Factory.OpenSession(); keyword = string.Format("%{0}%", keyword); // retrieve all posts in the database that contains the given keyword posts = session.CreateCriteria(typeof(Post)) .Add(Expression.Like("Title", keyword)) .AddOrder(new Order("LastUpdateDate", false)) .List(); // close a session to the backend database session.Close(); foreach (Post post in posts) { Console.WriteLine(post.PostID.ToString() + " : " + post.Title); } }

NHibernate.Expression命名空間中封裝了豐富的算符,如下表所示。

同時,NHibrenate還支持Query By Example(QBE)的查詢方式,使得對象查詢實現起來簡直是太簡單了!

3、更新Post對象

void UpdatePost(Post post) { ISession session = this.Factory.OpenSession(); Console.WriteLine("original Post title is : " + post.Title); // modify post title post.Title = "new title " + Guid.NewGuid().ToString(); session.Update(post, post.PostID); // retrieve updated post from database Post updatedPost = session.Load(typeof(Post), postId) as Post; Console.WriteLine("updated Post title is : " + post.Title); session.Close(); }

4、刪除指定的post對象

void Delete(Post post) { // start a data session ISession session = this.Factory.OpenSession(); // always start a transaction when handling the insert/update/delete operation ITransaction trans = session.BeginTransaction(); // delete current post record from to the backend database session.Delete(post); // commit a transaction trans.Commit(); // close a session to the backend database session.Close(); }

對於使用NHibernate進行對象的CRUD操作,本文就介紹到這裏,是否已經激起各位一起學習NHibernate的慾望?希望和大家一起交流,共同進步。

發佈了70 篇原創文章 · 獲贊 5 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章