对大部分Nhibernte操作,都写了一个Demo,映射文件全部手写(手疼),看完后会对Nhibernte有个全面的了解。不想看文字的,可以看看附件中的代码。
什么是Nhibernate
Nhibernate会把数据库中的表用对象图的形式表现出来,对开发人员来说,他们面对的不是底层的ADO,DateSet等结构,而是包含业务逻辑的对象。Nhibernate足够聪明,它能做到自动、透明的持久化对象图,这节省了大量的开发时间,也弥补了对象设计和数据库设计间的不对称性。
Nhibernte主要用来解决复杂的业务逻辑,而不适合简单逻辑或以数据为中心的系统。
Nhibernte中的几个重要对象
下面介绍Nhibernate中常用的几个对象,首先是Configuration
Configuration
Configuration负责管理Nhibernate的配置信息以及类与数据库之间的映射文件(*.hbm.xm),负责创建ISessionFactory。
Nhibernate可以通过下面两种方式进行初始化:
一、配置文件
配置文件是最常用的方式,灵活简单
<?xml version="1.0" encoding="utf-8" ?>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<session-factory name="sampledb">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="connection.connection_string">Data Source=DD-10980FA277D7;Database=sampledb;User ID=sa;Password=sa;</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="connection.isolation">ReadCommitted</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="default_schema">sampledb.dbo</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="show_sql">true</property>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<!--<property name="hibernate.current_session_context_class">NHibernate.Context.ManagedWebSessionContext</property>-->
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<mapping assembly="Domain" />
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</session-factory>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</hibernate-configuration>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
下面的代码会调用默认的hibernat.cfg.xml配置文件:
Configuration cfg = new Configuration().Configure();
如果要用非默认文件初始化可以用下面代码:
Configuration cfg = new Configuration().Configure(specificConfigName);
二、通过代码设置Configuration属性,这种方式不推荐使用。
通过配置文件名
Configuration cfg = new Configuration()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
.AddFile("Item.hbm.xml")
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
.AddFile("Bid.hbm.xml");
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
通过内嵌资源
Configuration cfg = new Configuration()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
.AddClass(typeof(NHibernate.Auction.Item))
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
.AddClass(typeof(NHibernate.Auction.Bid));
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
这种方式自动加载对应类名称的hbm.xml文件。
通过程序集
Configuration cfg = new Configuration()
.AddAssembly( "NHibernate.Auction" );
这种方式会加载指定程序集中所有的hbm.xml文件。
注意:Nhibernate需要的只是hbm.xml文件,而不需要每个文件对应的类,类信息有Nhibernte通过反射与动态代理得到。
ISessionFactory
ISessionFactory管理数据库的映射关系、二级缓存和Sql语句池,负责创建Session,重量级对象,一个数据库对应一个,不能频繁创建,一般采用单例模式。
下面语句创建了ISessionFactory
ISessionFactory sessions = cfg.BuildSessionFactory();
ISession
ISession作为Nhibernate的一级缓存,是最常用的对象,ISession的操作比较复杂,涉及到的内容很多,后面会详细介绍。
下面语句创建ISession
ISession session=sessions.OpenSession();
持久化类与映射文件
下面的例子实现最简单的持久化操作。
假定我们已经抽象出了某个业务领域的域模型:包含客户、订单。客户有客户名,订单包含订单号,并且要求根据订单能找到对应的客户信息。
首先创建持久化类
持久化类作为域对象使用,可以是标准的C#类,也可以是POCO类型,如果持久化类遵循POCO模型,Nhibernate可以工作的更好。
在最新的Nhibernate中,默认了属性的延迟加载,为了能够让动态代理创建持久化的代理对象,必须把熟悉设置为Virtual,否则通过lazy=false关闭延迟加载。
不要混淆持久化类与持久化状态,持久化类没有状态概念,它可以处于任何状态。
用C#实现上面的域模型
定义Customer:
public class Customer
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Customer()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Customer(string name)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
_name = name;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private int _id;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public virtual int Id
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _id; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _id = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private string _name;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public virtual string Name
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _name; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _name = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
定义Order,并建立到Customer的单向关联:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public class Order
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Order(string orderno,Customer c)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
_orderNumber = orderno;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
_customer = c;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Order()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private int _id;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public virtual int Id
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _id; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _id = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private string _orderNumber;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public virtual string OrderNumber
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _orderNumber; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _orderNumber = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private Customer _customer;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public virtual Customer Customer
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _customer; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
set
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
_customer = value;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
到此持久化类以及定义完,下面要做的是把它映射到表。在Nhibernate中通过配置文件实现映射,这保证了域模型的可移植性。
映射文件以nbm.xml作为后缀名,映射文件名称可以任意,但是最好和持久化类同名。
其次创建映射文件
Customer的映射文件
Customer.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<class name="Customer" table="CUSTOMERS" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<id name="Id" column="ID" type="Int32">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<generator class="native"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</id>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Name" column="NAME" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</class>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</hibernate-mapping>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
Order.hbm.xml
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<?xml version="1.0" encoding="utf-8" ?>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<class name="Domain.Order,Domain" table="ORDERS" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<id name="Id" column="ID" type="Int32">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<generator class="native"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</id>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="OrderNumber" column="Order_number" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<many-to-one name="Customer" class="Domain.Customer,Domain" column="Customer_Id" cascade="save-update"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</class>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</hibernate-mapping>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
配置文件完成下面的几类映射
一、首先通过OID建立对象引用和数据表主键间的映射
在.net中,通过引用来唯一标识一个对象,而在数据库中用主键唯一标识一条记录,因此必须建立对象与数据库表记录之间的一一对应关系。这种关系在Nhibernate中通过OID建立。
如Customer.hbm.xml
<id name="Id" column="ID" type="Int32">
<generator class="native"/>
</id>
OID通过id元素映射,通常对应表的主键(ID),但这也不是强制性的,OID的目的是为了建立一一映射关系。
二、建立类和表之间的关系
要建立下面几种映射:
通过class元素建立类名称与表名称的映射:
<class name="Domain.Order,Domain" table="ORDERS" />
通过property元素建立类属性和表字段的映射
<property name="Name" column="NAME" type="String"/>
Type可以为Nhibernate类型、.net类型自定义类型,此处用的是Nhibernate类型。
建立对象间关系和表关系的映射,如把对象单向多对一关联映射为外健关系
<many-to-one name="Customer" class="Domain.Customer,Domain" column="Customer_Id" cascade="save-update"/>
建立一些辅助功能,这些能让nhibernate把持久化做的更好,如:延迟加载,抓取策略以及为更好生成数据库schema而设置的特性(column 特性)等。
下面的配置为数据库架构生成器提供了更详细信息:
<property name="Name" >
<column name="NAME" sql-type="varchar" length="80"/>
</property>
到此,已经建立了持久化类和数据表的关系,以后就可以透明持久化数据,Nhibernate会把我们对持久化类的操作通过Sql映射到数据库。这时我们也从烦人的ADO中解脱出来,可以把精力放到业务关系上,着力解决实际问题,而不是技术问题。
最后要做的是通过Session把业务数据存储到数据库。
简单的CRUD操作,其中Session是Sessin接口的实例,例子中省去了Session管理。
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void Insert()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c1 = new Customer("ding");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(c1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void Select()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c1 = Session.Load<Customer>(1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void Update()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c1 = Session.Load<Customer>(1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
c1.Name = "dinghao";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(c1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void Delete()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c1 = Session.Load<Customer>(1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Delete(c1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
代码是不是很简单?Nhibernate就是如此简便。因为涉及到Session,稍做些解释,这些有利于后面其他概念的理解和优化Nhibernate。
Session作为一级缓存,维护着内存中的对象图,每当加载对象时Session就保存对象的一份引用,使之不被回收,作为缓存待用。如:
Customer c1 = Session.Load<Customer>(1);会创建Customer实例的两份引用,一份保存在c1,另一份保存在Session,这样即使c1不在引用Customer,只要Session不被情空,Customer对象仍然存活。
这样查询时如果缓存命中,就不会再读取数据库,提高了效率。
Customer c1 = new Customer("1");
Session.Save(c1);执行insert
Customer c2 = Session.Get<Customer>(c1.Id); //缓存中有数据,不会执行select。
Session还可以提供更优化的Sql,因为只有在清理缓存时才执行sql,这也就提供了一个优化sql的时机,这时可以通过一些策略来使Nhibernate生产更高效的sql语句,优化后面有更详细说明。
但是Session的缺点也很明显,它必须维护缓存于数据库的一致性,这造成没有办法实现高效的更新和删除操作,每次更新删除时必须通过执行查询,来保证Session不存在脏数据。如下面的删除操作
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void Delete()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c1 = Session.Load<Customer>(1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Delete(c1);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
首先执行Load,然后删除。这是Nhibernate不能解决的问题,是Session模型本身的缺陷,一些优化只能缓解这种性能损失,所以批量操作最好通过NativeSql。
Nhibernte1.2的文档说,通过把batch-size设置为0,SqlServer会执行批量更新、删除。没有经过测试。
或许后续版本会提供无状态的Session和bulk更新删除(Hibernate3)。
状态
对象分三种状态,理解状态是理解Session管理的基础
临时状态
对象位于内存,但没有被Session管理,不对应数据库记录。
持久状态
已经加入到Session中,由Session管理,Nhibernate负责持久化,有对应记录。
游离状态
没有被Session管理,但可能对应一条纪律,也可能没有。简单的说这条记录有主键值,Nh会把它作为游离态,否则作为临时态。
对象转换图
实体和值对象
Nhibernate中对象分两种,一种是值一种是实体,这是非常重要的概念。两者的本质区别是值没有OID,这就意味着值是个残缺的实体,他不能单独持久化,不能建立到实体的关联。
抓取策略
新版种通过lazy和fetch定义抓取策略,其中lazy定义什么时候检索数据,fetch定义如何检索数据。两种结合使用,lazy默认为true,fetch默认是select。
由于默认采用延迟加载,如果Session关闭后,访问没有被加载对象会抛异常,可以调用NhibernteUtil.Initialize();使其被加载。或者Session关闭前对数据做初始化。
Fetch默认采用select,这通常导致N+1问题,其中的一种解决方式是,把fetch设置为join,以采用左外链接检索。
批量检索,通过batch-size可以缩减生成的Select语句数量
查询方式
Hql
Hql是面向对象的查询语言,虽然看起来类似于sql,这只是为了让熟悉sql的用户更容易使用,Hql用到的是持久化类。
几个例子:
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void AgrigateFunction()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList customers = Session.CreateQuery("select max(c.Age),sum(c.Age) from Customer c").List();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(customers.Count);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void InnerJoin()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList customers =
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.CreateQuery("select c from Customer c inner join c.Orders o where c.Name like 'T%'").List
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(customers.Count);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void FetchLeftJoin()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList<Customer> customers =
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.CreateQuery("from Customer c left join fetch c.Orders o where c.Name like 'T%'").List
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
<Customer>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(customers.Count);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
QBC
提供面向对象的查询语法,不需要了解Sql,就可以使用。
如:
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void WhereSelect()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList<Customer> customers = Session.CreateCriteria(typeof(Customer)).Add(Expression.Eq("Name", "Tom")).List<Customer>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList<Customer> customers2 = Session.CreateCriteria(typeof(Customer)).Add(Expression.Eq("this.Name", "Tom")).List<Customer>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
下面是简单的Hql和QBC操作
NativeSql
最新的Nhibernte增强了本地sql查询,感觉可以比上Ibatise了,比以前好用很多。
如:实体查询,把sql语句查询结果自动映射到类
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void Entiy()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList<Customer> c = Session.CreateSQLQuery("select * from CUstomers").AddEntity(typeof(Customer)).List<Customer>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(c.Count);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
标量查询:把查询结果映射到集合
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void ScaleSelect()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList c =Session.CreateSQLQuery("select * from CUstomers").AddScalar("Name", NHibernateUtil.String)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
.AddScalar("Age", NHibernateUtil.Int32).List();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(c.Count);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
数据库设计和类设计
关系数据库和OO的不对称性,才使得ORM有用武之地,首先是粒度,数据库为了效率一般采用粗粒度模型,而OO为了重用性、简便性多采用细粒度模型。这要求Nhibernte必须能透明的再两者间转换。
其次是OO的一些特性,如关联、继承、多态、组合,在数据库中没有对应概念,这时Nhibernte要解决的第二个问题。
以关联为例,类有一对一,一对多,多对一,多对多关联,并且这些关系是有方向的。数据库并不存在这些关系,也没有任何方向问题,但是数据库通过SQL可以模拟任意的关联关系。所以只要设置好Nhibernte的映射元数据,就可以把对象关联映射到数据库。
后面有这几种映射方式的例子,见代码
把OO概念映射到数据库
下面的通过例子说明怎么映射OO概念到数据库,虽然分开说明,但他们不是孤立的。
映射关联关系
类的关联不一定需要映射到数据库,反之也一样。
管理分实体间的关联与实体到值对象的关联,其中实体关联最常用。
通过两种方式映射下面的关联关系
实体间的one2many关联
![](https://www.cnblogs.com/images/cnblogs_com/bluewater/Association.jpg)
代码:
private IList<Order> _orders;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual IList<Order> Orders
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _orders; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _orders = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
建立文件:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<bag name="Orders" table="ORDERS">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<key column="CUSTOMER_ID"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<one-to-many class="Domain.Order" not-found="exception"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</bag>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
如果不希望Order有自觉的生命期,可以建立实体与值对象间的关联,
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private IList<Order> _valueOrders;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual IList<Order> ValueOrders
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _valueOrders; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _valueOrders = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
映射文件:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<bag name="ValueOrders" table="ORDERS">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<key column="CUSTOMER_ID"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<composite-element class="Order">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="OrderNumber" column="Order_number" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Price" column="PRICE" type="Decimal"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</composite-element>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</bag>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
测试代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public void ComponentSet()
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c = new Customer("ding");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList<Domain.Order> os = new List<Domain.Order>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
os.Add(new Domain.Order("dd",3));
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
c.ValueOrders = os;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(c);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
映射组成关系
组件在Nhibernate中用于映射对象间的组成关系
组件是值对象(Value),用Componet以及包含Component的其他元素映射。
如,映射下面的模型
<component name="HomeAddress" class="Address">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Street" type="String" column="HOME_STREET"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="City" type="String" column="HOME_CITY"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Province" type="String" column="HOME_PROVINCE"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="ZipCode" type="String" column="HOME_ZIPCODE"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</component>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<component name="CompanyAddress" class="Address">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Street" type="String" column="COM_STREET"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="City" type="String" column="COM_CITY"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Province" type="String" column="COM_PROVINCE"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="ZipCode" type="String" column="COM_ZIPCODE"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</component>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private Address _homeAddress;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual Address HomeAddress
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _homeAddress; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _homeAddress = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private Address _companyAddress;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual Address CompanyAddress
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _companyAddress; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _companyAddress = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
测试代码
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[TestFixture]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Category("Composite")]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public class Composite:NhSession
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void SaveAll()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c = new Customer("ding");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Address ha = new Address("ha", "bj", "hb", "0000");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Address ca = new Address("ha", "bj", "hb", "0000");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(c);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void SaveWithoutComponent()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c = new Customer("ding");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(c);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void NullSemantic()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c = new Customer("ding");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(c);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Customer c2 = Session.Load<Customer>(c.Id);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Assert.IsNull(c2.HomeAddress);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
映射继承关系以及多态
映射继承有下面三种方式:
http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
http://www.martinfowler.com/eaaCatalog/classTableInheritance.html
http://www.martinfowler.com/eaaCatalog/concreteTableInheritance.html
现在以例子说明table per class与concrete table inheritance继承方式。
假设存在下面的对象关系:
如果用为了提高数据库效率,可以通过一个表映射继承,也就是单表继承
首先再数据库设置一个标志例,该列说明雇员的类型。
程序代码:
见附件
映射关系:
<?xml version="1.0" encoding="utf-8" ?>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Inheritance">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<class name="IEmployee" table="Employees">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<id name="Id" column="ID" type="Int32">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<generator class="native"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</id>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<discriminator column="EMPLOYEE_TYPE" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Name" column="NAME" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<subclass name="SalariedEmployee" discriminator-value="se" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Salary" column="Salary" type="Int32"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</subclass>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<subclass name="HourlyEmployee" discriminator-value="he">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<property name="Rate" column="Rate" type="Int32"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</subclass>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</class>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</hibernate-mapping>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
测试代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[TestFixture]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Category("PerClassInheritence")]
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public class PerClassInheritence:NhSession
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void SaveSubClass()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IEmployee se = new SalariedEmployee("ding",3);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(se);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
/// 多态查询
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
/// </summary>
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void GetBase()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IList<IEmployee> es= Session.CreateQuery("from IEmployee").List<IEmployee>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(es.Count);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Test]
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void GetSubBase()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int id = SaveHourEmployee();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IEmployee es = Session.Get<HourlyEmployee>(id);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.Write(es.ToString());
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private int SaveHourEmployee()
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IEmployee he = new HourlyEmployee("ding", 3);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Session.Save(he);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return he.Id;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
这种方式至持多态查询。
一个具体类一个表,这种方式不能映射基类,所以不支持多态查询。
代码省略,见附件
集合映射
集合映射分两类,一是实体类型集合,如关联的多端,另一类是值类型集合。集合映射有两种语义,一种是.net中集合的概念,另一种是nhibernate中集合的概念,前种在代码文件中体现,后一种体现在映射文件中。如用bag映射IList,ICollection。
集合对应数据库中的表,表必须存在外键、做为集合元素的列,如果用含有索引语义的集合做映射,还必须包含能做索引的项。
这部分和关联关系密切,可以结合理解。
代码种经常会使用到集合,下面看看怎么把集合映射到数据库。
假设有下面的代码
private ISet<string> _images;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual ISet<string> Images
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _images; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _images = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private IDictionary<string,string> _mapImages;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual IDictionary<string,string> MapImages
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _mapImages; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _mapImages = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private IList<Order> _valueOrders;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public virtual IList<Order> ValueOrders
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _valueOrders; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _valueOrders = value; }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
映射Set,set是无序,没有索引,没有重复值的集合
<set name="Images" table="Image" >
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<key column="Customer_id" />
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<element column="FileName" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</set>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
映射Map,map包含键值对
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<map name="MapImages" table="Image">
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<key column="Customer_id"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<index column="FileName" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
<element column="ImageName" type="String"/>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
</map>
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
映射组件
见关联关系
集合排序,分两种一种为内存排序,另一种为通过Sql排序。内存排序可以通过实现IComparer接口,实现自定义排序。Sql排序通过order-by特性制定列名及排序机制,如:order-by=“Filename desc”
怎么理解Nhibernte
理解NHibernate,应该从对象开始,即总是要考虑如何把对象映射到对应的数据库结构,而不是反过来思考。
考虑Nhibernte生成的Sql是否过量,如果是考虑优化。
Nhibernate,确实很复杂,我们用到的一般只是他的一部分功能。
开发方式
开发可以从数据库建模开始,也可以从OO建模开始。
如果从数据库开始,就要把数据库表映射为类、hbm.xml文件。反之则把OO映射为表、hbm.xml文件。
由于Nhibernte可以可以隔离类和数据库,我认为这种情况下两种方式区别已经不大,主要的问题在于哪知能更好的自动生成,以及在以后修改一方时能更好的自动更正另一方。
不过最重要的一点是,不论从哪一方开始设计,最终的对象都不能是表的直接映射,否则采用Nhibernte也就没有什么意义了。
好像还可以同时进行,建立抽象模型后,一边设计数据库,一边设计持久化类,最后用hbm.xml映射两者的关系。这种方式好像是最优的,缺点就是没有办法用自动生成工具,工作量较大。
辅助工具
最常用的是通过书库架构生成类和映射文件,目前支持1.2的工具不多,下面是支持1.2的模版:http://www.codeproject.com/useritems/NHibernate_Templates.asp
但是必须要明确的是,生成的类一定要看看是否符合OO的标准,不要把任何表都映射为类。
其他工具包括,通过hbm.xml生成数据库,通过特性映射而不用写hbm.xml
资料
中文:孙卫琴,精通hibernte,java对象持久化技术详解
英文:nhibernate referenc,hibernate in action,Nhibernae in action(十月出版)
认真写了好久的例子:
https://files.cnblogs.com/bluewater/nhiebernatedemo.rar
为什么不选用ActiveRecord
http://www.cnblogs.com/bluewater/archive/2007/08/14/855557.html