(一)Nuget下载NHibernate和MySQL.Data
(二)配置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!--以下是需要在App.config中添加configSection。这个应该放在startup元素前面-->
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,Nhibernate"/>
</configSections>
<!--以下是vs生成的,保留-->
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<!--以下是需要在App.config中添加的NHibernat的配置信息。需要注意的是,dialect要选择与使用的数据库对应的dialect-->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
<property name="connection.connection_string">
Server=localhost;Database=newbooks;User ID=root;Password=8888
</property>
<property name="dialect">NHibernate.Dialect.MySQL55Dialect</property>
<!--当选用MySQL5.5时,要选择NHibernate.Dialect.MySQL55Dialect,不要选择NHibernate.Dialect.MySQL5Dialect,否则
在对<Id>进行映射的时候,会把数据库中的类型设为BINARY(16),当存入数据时又会报告Guid类型的数据超出长度的异常-->
</session-factory>
</hibernate-configuration>
</configuration>
以上配置中,需要强调的是,dialect要选对。关于更详细的配置属性,可参考有关NHibernate文档。
(三)Mapping文件
使用xml格式的映射文件必须以hbm.xml作为文件名的结尾,比如
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="DDDPPP.Chap21.NHibernateExample.Application.Model.Auction"
assembly="DDDPPP.Chap21.NHibernateExample.Application">
<class name="Auction" table="Auctions" lazy="false">
<id name="Id" type="Guid" column="Id"/> <!--(1)最简单的写法,type指Hibernate的数据类型,不是数据库中的数据类型。这种写法表示Id是由程序赋值的,而不是Hibernate或数据库自动生成ID。需要说明的是,在Hibernate配置中要把Dialect配置正确,与数据库版本对应起来,否则如果用的5.5版本MySQL,而配置用用MySQL5Dialect而不是MySQL55Dialect,映射会出现问题-->
<!--<id name="Id" type="Guid">
<column name="Id"/>
</id>-->
<!--(2)上面的写法与(1)的写法等效。需要说明的是,在Hibernate配置中要把Dialect配置正确,与数据库版本对应起来,否则如果用的5.5版本MySQL,而配置用用MySQL5Dialect而不是MySQL55Dialect,映射会出现问题-->
<!--<id name="Id" type="Guid">
<column name="Id" sql-type="VARCHAR(36)"/>
</id>-->
<!--(3)上面的写法中多了sql-type属性,该属性表示数据库中的而数据类型指定为VARCHAR(36)。通常省略不写,由Hibernate自行管理。-->
<!--<id name="Id" type="Guid" column="Id" >
<generator class="guid" />
</id>-->
<!--(4)上面的写法表示Id自动生成。生成类型为guid-->
<version name="Version" column="Version" type="Int32" unsaved-value="0"/>
<component name="StartingPrice" class="Money">
<property name="Value" column="StartingPrice" not-null="true"/>
</component>
<property name="EndsAt" column="AuctionEnds" not-null="true"/>
<component name="WinningBid" class="WinningBid">
<property name="Bidder" column="BidderMemberId" not-null="false"></property>
<property name="TimeOfBid" column="TimeOfBid" not-null="false"></property>
<component name="MaximumBid" class="Money">
<property name="Value" column="MaximumBid" not-null="false"></property>
</component>
<component name="CurrentAuctionPrice" class="Price">
<component name="Amount" class="Money">
<property name="Value" column="CurrentPrice" not-null="false"/>
</component>
</component>
</component>
</class>
</hibernate-mapping>
(1)最简单的写法<id name="Id" type="Guid" column="Id"/> ,type指Hibernate的数据类型,不是数据库中的数据类型。这种写法表示Id是由程序赋值的,而不是Hibernate或数据库自动生成ID。
(2) <id name="Id" type="Guid">
<column name="Id"/>
</id>的写法与(1)写法等效。
(3)元素column中可以添加sql-type属性,明确指定数据库中的数据类型,常常是省略的。
<column name="Id" sql-type="VARCHAR(36)"/>
(4)如果要自动生成Id,则写法可以如下:
<id name="Id" type="Guid" column="Id" >
<generator class="guid" />
</id>
(5)需要说明的是,在Hibernate配置中要把Dialect配置正确,与数据库版本对应起来,否则如果用的5.5版本MySQL,而配置用用MySQL5Dialect而不是MySQL55Dialect,映射会出现问题。
(6)Mapping文件可以放在指定程序集的任何位置。
(四)初始化
当配置文件和Mapping文件都准备好了以后,就可以初始化NHibernate。
(1)初始化
Configuration config = new Configuration();
config.AddAssembly("这里替换为包含Mapping文件的程序集名称"); //这里把包含Mapping文件的程序集名称告诉config,便于config扫描程序集找到所有hmb.xml结尾的文件并读取映射信息
// config.AddFile("Infrastructure\\Auction.hbm.xml"); //如果不采用上面的AddAssembly方法,也可以直接添加对应的文件路径,该路径表示相对于最终生成的程序文件夹(Debug,Release)中的相对路径
config.Configure(); 执行构造
(2)自动生成数据库表
可以使用NHibernate来初始化数据库生成对应的表(注:如果数据库已经有了,不需要这一步;或者可以直接生成手工写SQL命令创建数据库表,若这样,也不要这一步)
当完成初始化后,用以下代码可以生成表:
var schemaExport = new SchemaExport(config);
schemaExport.Create(true, true);
可以做一个Project专门管理数据库表的生成和更新,避免把这个放在应用程序项目中每次都去生成数据库表。
(3)使用NHibernate
config初始化完成后,可以使用BuildSessionFactory()方法创建sessionFactory,然后可以用SessionFactory的OpenSession方法取得ISession对应,从而利用ISession对象实现数据的管理。具体ISession的使用方法,百度一下很方便找到。
var sessionFactory = config.BuildSessionFactory();
var s=sessionFactory.OpenSession();
(4)CurrentSessionContext
通过SessionFactory对象取得Session 的常用两个方法,分别为OpenSession()和 GetCurrentSession(),前者为新创建一个Session,后者为取得当前的Session(需要利用CurrentSessionContext类的静态方法Bind()先绑定由OpenSession()方法创建的实例,然后GetCurrentSession()才能获得当前实例。
一种可行的代码案例如下:
using(var session=_sessionFactory.OpenSession())
{
CurrentSessionContext.Bind(session); //绑定
using(var transaction=session.BeginTransaction())
{
//调用某个repository对象中的方法,在该方法中还将用到session对象。一张方式是把session传过去;另一种是该repository张先前创建的时候已经通过IOC注入了_sessionFactory对象,这时可以直接使用该_sessionFactory的GetCurrentSession()来获取当前绑定的session
}
CurrentSessionContext.Unbind(_sessionFactory);//解除绑定
}
为了配合GetCurrentSession()方法的使用,需要在NHibernate的配置xml中设置current_session_context_class属性,比如:
<property name="current_session_context_class"> thread_static</property>