建立一个Company类用来测试,对应的表为TBLCOMPANY。
1.
下载NHibernate(版本1.2.0.CR1),将NHibernate
\bin\net-2.0下面的文件拷贝到lib目录。
2. 为实体建立Class
Library的Domain工程。为工程添加\lib\Iesi.Collections.dll文件的引用(以后用)。
3.
Company类的代码如下
using
System;
using
Iesi.Collections.Generic;
namespace
NH12.MyExample.Domain
{
#region
Company
public class
Company
{
private string
_companyID;
private string
_companyName;
public Company(string id, string
name)
{
_companyID =
id;
_companyName =
name;
}
public
Company()
{
}
public
virtual string CompanyID
{
get {
return _companyID; }
set { _companyID = value;
}
}
public virtual string
CompanyName
{
get { return
_companyName; }
set { _companyName = value;
}
}
#region
override
public override bool Equals(object
obj)
{
if (this == obj) return
true;
if (obj == null || obj.GetType() !=
this.GetType())
return
false;
Company company = obj as
Company;
return company != null &&
company.CompanyID ==
_companyID;
}
public override
int GetHashCode()
{
return
_companyID.GetHashCode();
}
public
override string
ToString()
{
return
_companyID;
}
#endregion
}
#endregion
}
4.
将NHibernate源代码中的nhibernate-mapping.xsd文件拷贝到Domain工程的目录下,也可以拷贝到VS
2005的系统目录,这是因为映射文件使用这个xsd进行校验、输入提示等。为Domain工程添加Company.hbm.xml映射文件,在文件的属性->Build
Action中选择Embedded Resource,文件内容如下
<?xml
version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2" namespace="NH12.MyExample.Domain"
assembly="Domain">
<class name="Company"
table="TBLCOMPANY">
<id name="CompanyID"
>
<column name="COMPANY_ID" sql-type="nvarchar" length="4"
not-null="true"/>
<generator class="assigned"
/>
</id>
<property
name="CompanyName">
<column name="COMPANY_NAME" length="70"
sql-type="nvarchar" not-null="true"
/>
</property>
</class>
</hibernate-mapping>
5. 添加一个Console
Application的NHTest工程。为工程添加\lib\Iesi.Collections.dll、\lib\NHibernate.dll文件的引用,添加Domain项目引用。
6.
将NHibernate源代码中的nhibernate-configuration.xsd文件拷贝到NHTest工程的目录下,也可以拷贝到VS
2005的系统目录,这是因为配置文件使用这个xsd进行校验、输入提示等。
在NHTest的App.config文件中添加如下配置:
<configSections>
<section
name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler,
NHibernate"
/>
</configSections>
<hibernate-configuration
xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property
name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
<property
name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property
name="connection.connection_string">Server=localhost;initial
catalog=NH;user id=sa;password=123</property>
<property
name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property
name="use_proxy_validator">False</property>
<mapping
assembly="Domain"
/>
</session-factory>
</hibernate-configuration>
数据库连接字符串信息改成自己的。注意1.2版本中配置信息不再支持方式,而改用property元素,相应的name只需要把原来name值中的nhibernate.这个前缀去掉就可以,value的方式没有发生变化。
7.
写代码测试。测试代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
NH12.MyExample.Domain;
using
NHibernate;
using
NHibernate.Cfg;
using
Iesi.Collections.Generic;
namespace
NH12.MyExample.Test
{
class
Program
{
static void
Main(string[]
args)
{
ISessionFactory
sessionFactory = new
Configuration().Configure().BuildSessionFactory();
ISession
session = null;
ITransaction trans =
null;
try
{
session
= sessionFactory.OpenSession();
trans =
session.BeginTransaction();
Company company = new
Company("1000", "BenQ Guru Co.,
Ltd.");
session.Save(company);
Console.WriteLine("company
1000 has been created");
Company company2 = new
Company("2000", "test company
2");
session.Save(company2);
Console.WriteLine("company
2000 has been created");
Company company3 =
session.Get("1000");
Console.WriteLine("Company : id:
{0} name: {1}", company3.CompanyID,
company3.CompanyName);
trans.Commit();
}
catch
(Exception
e)
{
trans.Rollback();
}
finally
{
session.Close();
}
sessionFactory.Close();
Console.ReadLine();
}
}
}
现在可以运行这个最简单的映射示例,运行完之后可以在TBLCOMPANY表中查询到记录。
即使是最简单的例子,我们也可以发现一些东西。
如果你一边单步执行,一边打开SQL
Server的SQL Profiler进行监控(监控的Event为Stored
Procedures中的RPC:Completed),可以发现,在两个session.Save()方法以及session.Get<>()方法处,并没有产生任何跟数据库进行交互的SQL语句,而只有在trans.Commit()的时候,才会产生下面这样两条SQL:
exec
sp_executesql N‘INSERT INTO TBLCOMPANY (COMPANY_NAME, COMPANY_ID) VALUES
(@p0, @p1)‘,
N‘@p0 nvarchar(19),@p1
nvarchar(4)‘,
@p0 = N‘BenQ Guru Co., Ltd.‘, @p1 =
N‘1000‘
exec sp_executesql N‘INSERT INTO TBLCOMPANY
(COMPANY_NAME, COMPANY_ID) VALUES (@p0, @p1)‘,
N‘@p0
nvarchar(14),@p1 nvarchar(4)‘,
@p0 = N‘test company
2‘, @p1 = N‘2000‘
这是因为NHibernate在同一个session内会做对象的状态管理和缓存,对对象属性的修改被缓存起来,直到事务提交的时刻才将所有数据库更新操作应用到数据库上;在session.Get()获取对象时,先从当前session的缓存中查找是否已经存在该对象,如果有,则直接取出这个对象,而不会产生一条SQL查询。所以上面的测试只有两个INSERT语句。
在上面测试的基础上,运行如下的测试代码
ISessionFactory
sessionFactory = new
Configuration().Configure().BuildSessionFactory();
ISession
session = null, session2=null;
ITransaction trans =
null;
try
{
session
= sessionFactory.OpenSession();
session2 =
sessionFactory.OpenSession();
trans =
session.BeginTransaction();
Company company =
session.Get("2000");
company.CompanyName = "My Test
Company ...";
Company company2 =
session2.Get("2000");
session.Update(company);
trans.Commit();
}
catch
(Exception
e)
{
trans.Rollback();
}
finally
{
session.Close();
session2.Close();
}
sessionFactory.Close();
Console.ReadLine();
执行的SQL语句如下:
exec
sp_executesql
N‘SELECT company0_.COMPANY_ID as
COMPANY1_0_0_, company0_.COMPANY_NAME as
COMPANY2_0_0_
FROM TBLCOMPANY company0_ WHERE
company0_.COMPANY_ID=@p0‘,
N‘@p0 nvarchar(4)‘, @p0 =
N‘2000‘
exec
sp_executesql
N‘SELECT company0_.COMPANY_ID as
COMPANY1_0_0_, company0_.COMPANY_NAME as
COMPANY2_0_0_
FROM TBLCOMPANY company0_ WHERE
company0_.COMPANY_ID=@p0‘,
N‘@p0 nvarchar(4)‘, @p0 =
N‘2000‘
exec sp_executesql N‘UPDATE TBLCOMPANY SET
COMPANY_NAME = @p0 WHERE COMPANY_ID = @p1‘,
N‘@p0
nvarchar(19),@p1 nvarchar(4)‘, @p0 = N‘My Test Company ...‘, @p1 = N‘2000‘
其中第1、2句分别在session.Get()和session2.Get()调用时产生,因为这是两个不同的session,并且缓存中都还没有要取的company对象。第3句是在trans.Commit()时产生的。
www.lefeng123.com
另外一点需要注意,NHibernate不允许修改主键值,如果有修改,在事务提交时会丢出一个异常。这个特性在使用业务上有意义的字段作为主键时可能会面临一些问题,不过从另一个方面看,就算这种情况下NH允许修改主键,因为其它对象可能已经根据这个主键值引用该对象,所以修改同样会造成问题。至少目前我接触的项目中,对象的业务主键是不允许修改的。托福答案