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的欲望?希望和大家一起交流,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值