abluedog

闲来无胜情,沽酒买一醉;闻歌知雅意,笑看是与非。

统计

常用链接

留言簿(9)

阅读排行榜

评论排行榜

NHibernate Step by Step (一) Hello,NHibernate!

NHibernate Step by Step (一)  Hello,NHibernate!
 好了,今天我们正式开始NHibernate的历程,在第一次的练习中,我将尽量详细地讲解环境的配置,以后将不再详细解释。

基本的软件环境如下:
1.NHibernate www.nhibernate.org 当前版本是1.0.2
2.Code Smith http://www.codesmithtools.com/
3.NHibernate模板 点击这里下载
当然,少不了VS2005跟SQLServer了,我这里用的是SQLServer2005,教程用在SQLServer2000上应该没有问题,默认情况下,我将建立并使用一个叫NHibernate的数据库。

首先,我们先建立一个最简单的Person表,如下完整脚本(你可以进行修改以适合自己的数据库):

USE [NHibernate]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Person](
    [id] [
int] IDENTITY(1,1) NOT NULL,
    [name] [varchar](
50) COLLATE Chinese_PRC_CI_AS NOT NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (IGNORE_DUP_KEY 
= OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

仅有两个字段,一个自动增长的id,一个name,如下:

 
然后将下载的nhibernate-template解压,打开Code Smith,将模板加入”Template Explorer”,如下:

 
然后在其中的NHibernate.cst上点右键,选择“Execute”,弹出设置窗口,在左边的属性窗口进行如下设置:

 
注意:SourceDatabase属性在第一次选择时需要配置一个连接字符串,配置好后Code Smith将记录下来。 Assembly属性代表的是生成文件的默认Assembly名,而NameSpace,顾名思义,就是使用的命名空间了,这里我们全部使用”Test.Model”,请记住这个名字,点击左下角的Generate,将会在指定的输出目录下产生两个文件:Person.cs,Person.hbm.xml。

好了,NHibernate需要的类文件和映射文件生成完了,我们可以开始干活了!(生成NHibernate文件均是如此步骤,以后不再赘述)

新建立一个类库工程,为了简洁起见,我们命名为Model,需要注意的是,为了跟刚才生成的文件对应,我们需要在Model工程的属性页中将起Assembly名字设为上面的“Test.Model”,如下:

 
然后将刚才生成的两个文件Person.cs和Person.hbm.xml加入到Model工程中来,选中Person.hbm.xml文件,在属性窗口中将其“Build Action”设置为“Embedded Resource”(这是非常重要的一步,否则NHibernate将无法找到映射文件),如下:
 

build,ok,通过。

然后建立一个控制台工程,命名为Console1,添加NHibernate和上面Model项目的引用,另外添加一个应用程序配置文件,如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<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.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
    
<add key="hibernate.connection.connection_string" value="Server=localhost;Initial Catalog=NHibernate;Integrated Security=SSPI" />
    
<add key="hibernate.connection.isolation" value="ReadCommitted"/>
    
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
  
</nhibernate>

</configuration>


然后编写如下代码:

using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using Test.Model;

namespace Console1
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            Configuration config 
= new Configuration().AddAssembly("Test.Model");
            ISessionFactory factory 
= config.BuildSessionFactory();
            ISession session 
= factory.OpenSession();

            Person person 
= new Person();
            person.Name 
= "Jackie Chan";

            ITransaction trans 
= session.BeginTransaction();
            
try
            
{
                session.Save(person);
                trans.Commit();
                Console.WriteLine(
"Insert Success!");
            }

            
catch (Exception ex)
            
{
                trans.Rollback();
                Console.WriteLine(ex.Message);
            }

        }

    }

}


运行,ok,执行成功!!
我们到数据库检查一下,如下:

 
我们想要添加的记录已经成功加入到数据库中!!
是不是感觉有些神奇啊?好,我们开始详细解释。
先来看生成的两个文件,第一个是Person.cs,如下:

using System;
using System.Collections;

namespace Test.Model
{
    
Person
}


你可以发现,这完全是一个普通的poco类(Plain Old CLR Object),仅仅是对数据库person表的一个完全映射,不依赖于任何框架,可以用来作为持久化类,你可以在任何地方使用而不用担心依赖于某些神秘的运行时东西。

另外,NHibernate需要知道怎样去加载(load)和存储(store)持久化类的对象。这正是NHibernate映射文件发挥作用的地方。映射文件告诉NHibernate它应该访问数据库(database)里面的哪个表(table)及应该使用表里面的哪些字段(column),这就是我们今天要讲的重点了,Person.hbm.xml,如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
 
<class name="Test.Model.Person, Test.Model" table="Person">
  
<id name="Id" type="Int32" unsaved-value="0">
   
<column name="id" sql-type="int" not-null="true" unique="true" index="PK_Person"/>
   
<generator class="native" />
  
</id>
  
<property name="Name" type="String">
   
<column name="name" length="50" sql-type="varchar" not-null="true"/>
  
</property>
 
</class>
</hibernate-mapping>


不用说,最顶层的hibernate-mapping节点是NHibernate用来进行映射的根了,其中,包含一个class节点,里面的name属性对应我们的Person类,注意,需要完整的限定名;而table属性,则显而易见是对应数据库中的Person表了。
我们再往里面看,分别有两个节点,一个是id,对应数据库中的id,一个是属性name,对应表中的column name和Person类中的name属性,整个映射文件简捷明了,一看即知。实际上这是由代码产生工具产生的映射文件,里面很多东西我们其实可以省略,如下写法:
<property name=”Name” column=”name” />
NHibernate将自动去匹配数据库中的列而不需要我们来设置。

下面,我们来看一下应用程序配置文件中都记录了那些东西,如下:
hibernate.connection.provider_class  
定制IConnectionProvider的类型.
例如:full.classname.of.ConnectionProvider (如果提供者创建在NHibernate中), 或者 full.classname.of.ConnectionProvider, assembly (如果使用一个自定义的IConnectionProvider接口的实现,它不属于NHibernate)。
 
hibernate.connection.driver_class  
定制IDriver的类型.
full.classname.of.Driver (如果驱动类创建在NHibernate中), 或者 full.classname.of.Driver, assembly (如果使用一个自定义IDriver接口的实现,它不属于NHibernate)。

hibernate.connection.connection_string  
用来获得连接的连接字符串.

hibernate.connection.isolation  
设置事务隔离级别. 请检查 System.Data.IsolationLevel 来得到取值的具体意义并且查看数据库文档以确保级别是被支持的。
例如: Chaos, ReadCommitted, ReadUncommitted, RepeatableRead, Serializable, Unspecified

hibernate.dialect 
NHibernate方言(Dialect)的类名 - 可以让NHibernate使用某些特定的数据库平台的特性
例如: full.classname.of.Dialect(如果方言创建在NHibernate中), 或者full.classname.of.Dialect, assembly (如果使用一个自定义的方言的实现,它不属于NHibernate)。

接着,我们开始解释代码的执行,如下:

 

 

Configuration config = new Configuration().AddAssembly("Test.Model");

//通过配置对象来产生一个SessionFactory对象,这是一个Session工厂,
//那么Session是用来干什么的呢?一个Session就是由NHibernate封装
//的工作单元,我们可以近似地认为它起到ADO.Net中Connection的作用。
ISessionFactory factory = config.BuildSessionFactory();
ISession session 
= factory.OpenSession();

Person person 
= new Person();
person.Name 
= "Jackie Chan";

//这里,开启一个由NHibernate封装的事务,当然,在这里最终代表
//的还是一个真实的数据库事务,但是我们已经不需要再区分到底是
//一个SqlTransaction还是一个ODBCTransaction了
ITransaction trans = session.BeginTransaction();
try
{
    
//保存,提交,就这么简单!!
         session.Save(person);
        trans.Commit();
        Console.WriteLine(
"Insert Success!");
}

catch (Exception ex)
{
        trans.Rollback();
        Console.WriteLine(ex.Message);
}


现在有了一个基本的概念了吧??
好了,第一篇就讲这么多,我们下次再接着练习。

Step by Step,顾名思义,是一步一步来的意思,整个教程我将贯彻这一理念,待此系列结束后,我们再就某些高级话题进行深入。
任何建议或者批评,请e:abluedog@163.com

posted on 2006-04-15 12:47 abluedog 阅读(18275) 评论(163)  编辑 收藏 所属分类: NHibernate

评论

#1楼  2006-04-15 13:17 csdn shit! [未注册用户]

写点有新意的吧,拜托,太老套了!!!   回复  引用    

#2楼  2006-04-15 13:21 torome      

适合新手,不错。   回复  引用  查看    

#3楼  2006-04-15 13:22 皇帝的新装      

给没有接触过的人看是有必要的。继续努力。   回复  引用  查看    

#4楼  2006-04-15 13:25 support [未注册用户]

多谢了,好冬冬   回复  引用    

#5楼  2006-04-15 13:26 福娃      

写的很详细,期待。。。   回复  引用  查看    

#6楼  2006-04-15 13:33 Dflying Chen      

提一点建议,代码的格式可以设置得好一点。   回复  引用  查看    

#7楼  2006-04-15 14:10 福娃      

在net1.1上需要修改两个地方
using System.Collections.Generic;
改为
using System.Collections;
========================================
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System,
Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />

改成
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  回复  引用  查看    

#8楼 [楼主] 2006-04-15 14:17 abluedog      

@福娃
实际上,在我上面的演示代码里其实也应该添加System.Collections引用的,因为目前nhibernate官方还不支持generic,一个query对象返回的还是一个普通的IList。
第3方的nhibernate generic方案请参考:
http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx   回复  引用  查看    

#9楼  2006-04-15 14:23 剑在上海 [未注册用户]

挺!,之前还没接触过NHibernate,现在有点看懂了,感谢abluedog能花时间写这么好的教程   回复  引用    

#10楼 [楼主] 2006-04-15 17:24 abluedog      

除了Code Smith外,还有My Generation等代码生成工具,都支持NHibernate文件的生成。
My Generation:http://www.mygenerationsoftware.com/portal/default.aspx
NHibernate Template:
http://www.mygenerationsoftware.com/phpBB2/viewtopic.php?t=1505   回复  引用  查看    

#11楼  2006-04-15 22:27 mzl [未注册用户]

thankfulness!   回复  引用    

#12楼  2006-04-15 23:55 javac [未注册用户]

感谢abluedog,找了很久都没找到这样的入门级教程,其他教程像参考手册,有点摸不着头脑!
数据库脚本在MS SQL 2000下没有直接运行成功,手动建立后导出脚本如下:
CREATE TABLE [dbo].[Person] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[name] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Person] WITH NOCHECK ADD
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
GO
好像少了ALTER TABLE [dbo].[Person] WITH NOCHECK ADD,不知道是不是2000和2005版本上的差别?

还要感谢福娃指出.net1.1上代码需要修改的地方!

继续期待后面的教程!   回复  引用    

#13楼  2006-04-17 10:26 a11s.net      

非常适合我,收藏了   回复  引用  查看    

#14楼  2006-04-17 22:16 卡卡.net      

Nhibernate.org一直不能访问,哪位网友提供NHibernate的下载地址?感谢。   回复  引用  查看    

#15楼  2006-05-23 10:34 karlsoft      

VS2005和SQLServer2005正版哪里有下﹐哪位有﹐共享一下。謝謝。   回复  引用  查看    

#16楼  2006-05-23 10:34 karlsoft      

VS2005和SQLServer2005正版哪里有下﹐哪位有﹐共享一下。謝謝。   回复  引用  查看    

#17楼  2006-05-25 12:06 karlsoft      

使用NHibernate在Web層在按鈕下實現這個﹐不能添加數據﹐請問什么原因﹐是不是配置文件有問題﹐在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.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect"/>
<add key="hibernate.connection.connection_string" value="server=MIS03;uid=sa;pwd=;"/>
</nhibernate>
我的代碼碼如下﹕
按鈕下實現如下:

Configuration cfg = new Configuration();
cfg.AddAssembly("GuestBook.Data");
ISessionFactory f = cfg.BuildSessionFactory();
ISession s = f.OpenSession();
ITransaction t = s.BeginTransaction();
Users newUser = new Users();
newUser.Name = "papersnake";
newUser.Password = "123456";
newUser.Email = "you@hotmail.com";
newUser.RegTime = DateTime.Now;
s.Save(newUser);
t.Commit();
s.Close();   回复  引用  查看    

#18楼  2006-06-13 14:43 感谢楼主 [未注册用户]

好东西,很适合入门,谢谢楼主!   回复  引用    

#19楼  2006-06-21 09:54 main      

应@karlsoft
应该检查下你的版本,1.2.0那个的,感觉和之前的差别蛮大。   回复  引用  查看    

#20楼  2006-07-14 17:33 USAF      

SQL Server用Code Smith生成Person.cs和Person.hbm.xml;如果MySQL數據庫用什麽工具可以生成呢? 點樣生成?   回复  引用  查看    

#21楼  2006-07-15 23:03 零度海洋      

推荐一个学习.NET的好站点..
http://www.zero163.com/sortinfo.asp?Classid=45

asp.net2.0 最新最全的资料
各类.net三方控件..   回复  引用  查看    

#22楼  2006-08-24 10:05 小草      

很好,正好想了解这方面的,我补充了一下在Oralce数据库的操作,有兴趣可以查看我的blogs : http://www.cnblogs.com/liubiqu/archive/2006/08/24/485016.html   回复  引用  查看    

#23楼  2006-08-25 17:54 viptell [未注册用户]

学习了,已经在vs2005 sql2000通过,明天接着下一课,谢谢老是,写的很明白!   回复  引用    

#24楼  2006-08-30 16:45 kegogo      

感谢abluedog,请教一个问题,有点摸不着头脑!
我照着你的方法去做,却发现老是报错,后经调查我发现原来是,竟然是nhibernate中有一个错误,那就是它要对属性成成的方法要判断它是否是Virtual如下:
在ProxyTypeValidator页下的CheckEveryPublicMemberIsVirtual方法它要检查所有公共的方法是否是Virtual,而检查属性则报错,请问这里为什么要进行这样检查,有什么好的解决方法吗?   回复  引用  查看    

#25楼  2006-09-13 14:43 zhongge [未注册用户]

to kegogo

你用的是1.2.0版本的NHibernate.dll
搂住用的是1.0.2的   回复  引用    

#26楼  2006-09-13 14:45 zhongge [未注册用户]

辛苦搂住了,希望能跟大家一起探寻Nhibernate的本质的东东:)   回复  引用    

#27楼  2006-09-18 11:41 turnright [未注册用户]

我也是遇到和kegogo一样的问题,用1.0.2就ok了,如果用1.2.0应该怎么改呢?
  回复  引用    

#28楼  2006-10-09 09:35 bluepig [未注册用户]

我刚开始接触NHiberate,楼主文章写道浅简易懂,支持支持!   回复  引用    

#29楼  2006-10-09 16:37 anmyan [未注册用户]

运行时出现这个错误是不是配置文件有什么问题啊
D:\AnStudy\Nhibtest\Nhibtest\obj\Debug\CSCA4.tmp Error generating Win32 resource: Error reading icon 'D:\AnStudy\Nhibtest\Nhibtest\App.config' -- データが無効です。
我的配置文件为

<configuration>
<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.connection.isolation" value="ReadCommitted" />
<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=test;uid=sa;pwd=;"/>
<add key="hibernate.cache.provider_class" value="NHibernate.Caches.SysCache.SysCacheProvider,NHibernate.Caches.SysCache" />
</nhibernate>
</configuration>   回复  引用    

#30楼  2006-10-17 15:03 xuexi [未注册用户]

你第三个图的class中outputdriectory 后面的字符串是什么啊?求?代表什么意思啊?   回复  引用    

#31楼  2006-10-24 09:09 lwei [未注册用户]

能否详细介绍一下Code Smith ??   回复  引用    

#32楼  2006-10-30 11:30 风吹河岸柳轻扬      

很不错,楼主加油   回复  引用  查看    

#33楼  2006-11-25 15:40 IT猎人      

哦,我知道了,原来是Server=localhost的问题,改为Server=(local)就可以了,另外连接超时的默认值是30秒,所以那里没有马上抛出异常,是我没有耐心等它个30秒,呵呵.
  回复  引用  查看    

#34楼  2006-11-29 16:36 9527 [未注册用户]

我是新手,为什么我照做的时候报错:
我Win2003,.net2.0 ,vs2005, sql2005,NHibernate.dll(1.0.2.0),CodeSmith4.0.0
报错的位置是:
Configuration config = new Configuration().AddAssembly("Test.Model");

An unhandled exception of type 'System.TypeInitializationException' occurred in Console1.exe

Additional information: The type initializer for 'NHibernate.Cfg.Configuration' threw an exception.   回复  引用    

#35楼  2007-01-20 01:02 iafpdael [未注册用户]

<a href="http://wfneoodu.com">pltlgmoi</a> [URL=http://zlofrpjs.com]blbvyacb[/URL] mxpslzuh http://sdlbhnax.com xuiswqlw vuccniwo   回复  引用    

#36楼  2007-01-20 03:01 rcgqzrdu [未注册用户]

[URL=http://cryfjhre.com]iwwpuplx[/URL] wjnhsyle http://sgqttdce.com pzurfmeu jbbzfaei <a href="http://mbfjwcqy.com">yfsnhwgw</a>   回复  引用    

#37楼  2007-01-21 02:17 pharmacy [未注册用户]

Nothing changes your opinion of a friend so surely as success - yours or his.   回复  引用    

#38楼  2007-01-21 04:26 paxil [未注册用户]

If you want creative workers, give them enough time to play.   回复  引用    

#39楼  2007-01-21 05:48 ultram [未注册用户]

Fiction is obliged to stick to possibilities. Truth isn't.   回复  引用    

#40楼  2007-01-21 07:52 buy cialis online [未注册用户]

Let not the sands of time get in your lunch.   回复  引用    

#41楼  2007-01-21 09:03 cheap viagra lathy pretermission [未注册用户]

Sometimes love will pick you up by the short hairs...and jerk the heck out of you.   回复  引用    

#42楼  2007-01-21