上一章节,我们了解了NHibernate的介绍和用途,那NHibernate如何引入到项目中,并且被运用呢,这一章我们开始操作吧!

  注:本材料开始本人研究3天研究出来的,绝对最新,请仔细阅读!!!

  首先要有准备工作:

  1、下载NHibernate:当前版本2.0.1(较新版本)下载地址:http://sourceforge.net/projects/nhibernate/

  2、下载CodeSmith:http://www.codesmithtools.com/
  3、下载NHibernate模板:https://files.cnblogs.com/abluedog/nhibernate_template.rar

  

  关于NHibernate2.1版本的一些说明:

NHibernate2.1版本改变了ByteCode延迟加载机制,有三种3种IoC框架动态代理方式,分别为:Castle框架、LinFu框架、Spring.Net框架。我们只要选择一种,在配置文件中配置proxyfactory.factory_class节点。

如果使用Castle.DynamicProxy2动态代理,引用NHibernate.ByteCode.Castle.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Castle.ProxyFactoryFactory,NHibernate.ByteCode.Castle</property>

如果使用LinFu.DynamicProxy动态代理,引用NHibernate.ByteCode.LinFu.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.LinFu.ProxyFactoryFactory,NHibernate.ByteCode.LinFu</property>

如果使用Spring.Aop动态代理,引用NHibernate.ByteCode.Spring.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Spring.ProxyFactoryFactory,NHibernate.ByteCode.Spring</property>

另外NHibernate2.1要求.NET2.0 SP1以上版本 (System.DateTimeOffset),请使用VS2005的,务必打上Sp1补丁。推荐使用VS2008以上版本。

  OK,准备工作结束,开始讲解如何运用这3个工具:

  首先打开CodeSmith(注意CodeSmith一定要注册),导入NHibernate模板:如图

  

  注意:我在网上搜索很多关于NHibernate模板,始终没有找到,这个模板算是比较好的,但是要修改一下类生成文件和映射生成文件的内容:

  1、打开NHibernate.class.cst,找到如下代码:把所有生成 get、set 的 public 修饰符改为 public virtual ,注绿色virtual为添加部分

  

代码
#region Public Properties

<% if (SourceTable.PrimaryKey.MemberColumns.Count == 1) {%>
public virtual <%= IdMemberType(SourceTable) %> <%= IdName(SourceTable) %>
{
get {return <%= IdMemberName(SourceTable) %>;}
<% if (IdMemberType(SourceTable) == "string" ) {%>
set
{
if ( value != null && value.Length > <%= ColumnLength(SourceTable.PrimaryKey.MemberColumns[0])%>)
throw new ArgumentOutOfRangeException("Invalid value for <%= IdName(SourceTable) %>", value, value.ToString());
<%= IdMemberName(SourceTable) %> = value;
}
<% } else { %>
set {<%= IdMemberName(SourceTable) %> = value;}
<% } %>
}
<% } %>

<% foreach(ColumnSchema column in SourceTable.NonKeyColumns) { %>
public virtual <%= MemberType(column) %> <%= PropertyName(column) %>
{
get { return <%= MemberName(column) %>; }
<% if (MemberType(column) == "string") {%>
set
{
if ( value != null && value.Length > <%= ColumnLength(column)%>)
throw new ArgumentOutOfRangeException("Invalid value for <%= PropertyName(column) %>", value, value.ToString());
<%= MemberName(column) %> = value;
}
<% } else { %>
set { <%= MemberName(column) %> = value; }
<% } %>
}

<% } %>
<% foreach(TableKeySchema foreignKey in SourceTable.ForeignKeys) { %>
public <%= ManyToOneClass(foreignKey) %> <%= ManyToOneName(foreignKey) %>
{
get { return <%= ManyToOneMemberName(foreignKey) %>; }
set { <%= ManyToOneMemberName(foreignKey) %> = value; }
}

<% if ((foreignKey.ForeignKeyTable == SourceTable) && (foreignKey.PrimaryKeyTable == SourceTable)) { %>
public virtual <%= CollectionType(foreignKey) %> <%= CollectionName(foreignKey) %>
{
get { return <%= CollectionMemberName(foreignKey) %>; }
set { <%= CollectionMemberName(foreignKey) %> = value; }
}

<% } %>
<% } %>
<% foreach(TableKeySchema primaryKey in SourceTable.PrimaryKeys) { %>
<% if (IsManyToManyTable(primaryKey.ForeignKeyTable)) { %>
public virtual <%= CollectionType(primaryKey) %> <%= CollectionManyToManyName(primaryKey) %>
{
get
{
if (<%= CollectionManyToManyMemberName(primaryKey) %>==null)
{
<%= CollectionManyToManyMemberName(primaryKey) %> = <%= NewCollectionType(primaryKey) %>;
}
return <%= CollectionManyToManyMemberName(primaryKey) %>;
}
set { <%= CollectionManyToManyMemberName(primaryKey) %> = value; }
}

<% } else if (IsOneToOneTable(primaryKey)) { %>
public virtual <%= OneToOneClass(primaryKey) %> <%= OneToOneName(primaryKey) %>
{
get { return <%= OneToOneMemberName(primaryKey) %>; }
set { <%= OneToOneMemberName(primaryKey) %> = value; }
}

<% } else if (IsSubClassTable(primaryKey)) { %>
<% } else { %>
public virtual <%= CollectionType(primaryKey) %> <%= CollectionName(primaryKey) %>
{
get
{
if (<%= CollectionMemberName(primaryKey) %>==null)
{
<%= CollectionMemberName(primaryKey) %> = <%= NewCollectionType(primaryKey) %>;
}
return <%= CollectionMemberName(primaryKey) %>;
}
set { <%= CollectionMemberName(primaryKey) %> = value; }
}

<% } %>
<% } %>


#endregion

  

  2、打开NHibernate.hbm.cst,映射由2.0改为2.2 

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class<%= ClassNameAtt(SourceTable) %><%= ClassTableAtt(SourceTable) %>>

  OK,NHibernate模板修改成功,开始生成实体与映射文件

  最近在做一个进销存联系,数据表多了点,不利于学习,但是你看明白了,可以做一个数据表的小例子,下面是数据表的截图:

  

  生成持久化类 与 映射文件

  右键NHibernate.cst点击Execute,出现下面界面

  

  OutputDirectory:你的实体与映射文件保存的文件夹,建议先保存到一个单独的文件夹;

  SourceDatabase:是你第一次选择时需要配置一个连接字符串,配置好后Code Smith将记录下来;

  Assembly:写上你的项目的实体类库名,比如我做的进销存,实体类库叫GoodsMnanage.Model,在以后的Configuration创建时需要加载这个名字;

  Namespace:写上你的实体文件产生的路径。

   如果不明白可以对比一下我的项目截图:

  

  开始配置项目

  开发工具:vs2005/vs2008,SQL2005

  首先建一个小的web项目,以往的材料全是简单的实体和一个控制台文件,今天我们运用到3层的web项目中:

  根据截图,我们可以在Model层中建2个文件夹,所有***.cs类全部放在Entities文件夹中

注意:NHibernate默认使用代理功能,要求持久化类不是sealed的,而且其公共方法、属性和事件声明为virtual。

也就是说所有生成属性的set、get方法必须写成下面这种类型:检查一下你的实体类是这样写的吗,这就是为什么我们要修改NHibernate模板成为Public Virture了

public virtual string Name
  {
    get { return name; }
    set{ name = value;}
  }

在这里,类中的字段要设置为virtual,否则出现“failed: NHibernate.InvalidProxyTypeException : The following types may not be used as proxies: NHibernateSample.Domain.Entities.Customer: method get_Id should be virtual,method set_Id should be virtual”异常。

  所有***.hbm.xml映射文件全部放在Mappings文件夹中;

注意:所有Mapping下的***.hbm.xml的属性中生成的操作默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,因为NHibernate是通过查找程序集中的资源文件               映射实体;否则出现“ failed: NHibernate.MappingException : No persister for: NHibernateSample.Domain.Entities.Customer”异常

  然后在DAO层中首先添加版本为2.0.1中的NHibernate.dll,然后建一个NHibernateHelper.cs类

  

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;

namespace GoodsManage.DAO
{
public static class NHibernateHelper
{
private static ISession session = null;
private static ITransaction trans = null;

/// <summary>
///获取打开的session
/// </summary>
/// <returns></returns>

public static ISession getSession()
{
      //这里的GoodsManage.Model就是我们在CodeSmith中配置生成文件时的Assembly中的内容
Configuration conf
= new Configuration().AddAssembly("GoodsManage.Model");
//建立工厂
      ISessionFactory factory = conf.BuildSessionFactory();
      //打开工厂
session
= factory.OpenSession();

return session;
}

/// <summary>
/// 获取事务
/// </summary>
/// <returns></returns>
public static ITransaction getTrans()
{
      //创建事务
trans
= session.BeginTransaction();
return trans;
}
}
}

  之后新建类写增删改查的方法,写个简单的Get方法:

public static TbUser getUserById(int userId)
{
TbUser user
= session.Get<TbUser>(userId);
return user;
}

  之后建DAL层,添加DAO的应用

public static TbUser getUserById(int userId)
{
TbUser user
= tb_UserServer.getUserById(userId);
return user;
}

  最后开始最后一层,表示层,最重要的就是web.config的配置:

  首先要在表示层添加DAO、DAL的应用,最重要的是添加NHibernate.ByteCode.Castle.dll的引用

   web.config的配置

代码
<configuration>
<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.MsSql2005Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.connection_string">Server=.;DataBase=db_GoodsManage;user id=sa;password=123456</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
</session-factory>
</hibernate-configuration>
<appSettings/>
<connectionStrings/>

  dialect:数据库版本,我用的Sql2005,如果是2000,可以写MsSql2000Dialect

  connection.provider:连接数据库的提供者Nhibernate

  connection.connection_string:连接数据库字符串

  proxyfactory.factory_class:(关于NHibernate2.1.0的说明)

注意:如果没有配置proxyfactory.factory_class,会出现:

The ProxyFactoryFactory was not configured.
Initialize 'proxyfactory.factory_class' property of the session-factory configuration section with one of the available NHibernate.ByteCode providers.
Example:
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
Example:
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>

  最后在新建一个页面:添加一个按钮,双击按钮

protected void Button1_Click(object sender, EventArgs e)
{
TbUser user
= tb_UserManage.getUserById(1);
Response.Write(
"<script>alert('" + user .Name + "')</script>");
}

 运行,点击按钮时

  好了,结束了,我们的总体配置NHibernate流程也告一段落了,希望大家能够看懂,我开始学习HQL了,希望早点学会,总结大家看,如果本节存在什么问题,请大家指出,感谢大家的支持!

posted on 2010-06-10 08:47  过往云烟  阅读(1521)  评论(1编辑  收藏  举报