您的位置:首页 > 其它

NHibernate学习手记(1) - 对象的简单CRUD操作

2007-06-18 14:08 330 查看
和许多开发人员一样,我非常反感(甚至是恐惧)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的欲望?希望和大家一起交流,共同进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: