我的NHibernate曲折之行

之前,看过很多NHibernate的东西。特别是 YJingLeeNHibernate之旅系列比较经典。看得多了,但是还没有真正的从头到尾的做过一边。今天从头到尾做了一遍,发现问题还真多。我就将我做的过程和在这中间碰到的问题跟大家分享一下。也可以让一些初学的朋友少走一些弯路,当然我碰到的很多问题在网上都能找到答案,我也就将一些需要注意点,和出错的点收集一下,然后放到一起,节省大家时间去疯狂Google。大致过程参照YJingLee的NHibernate之旅(2):第一个NHibernate程序。不过YJingLee用的是NUnit测试框架,我这里直接用了一个Windows Form项目来做测试。
     我用的开发环境:Visual Studio 2008SP1+SQL Server 2008 + NHibernate-2.1.0.GA最新版
     首先新建一个空的解决方案,命名为NHibernateSimpale,然后新建三个项目分别为DAL类库项目,Model项目,NHibernateTest窗体项目。
     然后删除掉自动生成的Class1.cs.

我这里为了演示这个流程,就只创建了一个最简单的数据库,在文章的末尾我会提供将源代码和数据库执行脚本下载。
     我新建了一个NHibernate数据库,然后新建三张表,经典的Student,Course,StudentCourse。其实真正用到了就一张表Student。
     我这里使用的O/R Mapping的工具是mygeneration。我将其生成的映射文件和实体类文件的两个文件夹Entities和Mappings拷贝至Model文件夹下面,然后将其包含进项目中。这里注意了,第一个问题出现了,我当时在生成映射文件的时候在另外一个路径下,所以生成的默认的命名空间需要改成我现在的Model.Entities的命名空间。   
    在NHibernateTest里面添加三个配置文件,App.config,NHibernateMSSQL.config,NHibernateOracle.config其中第一个是用来存放数据库的链接字符串的,当然后别的用途。第二个,第三个是用来做NHibernate的配置文件的。这里我是为了实现多数据库的NHibernate的支持。可以让程序有一个比较好的数据库的扩展性。下次如果要从MSSQL换成Oracle或者MYSql只要修改或者增加一个配置文件就OK。
    在DAL项目中添加两个类,GetStudent.cs,SessionManager.cs,第一个是用来获取学生信息的。第二个是用来管理NHibernate中的Session,可以说相当于一个帮助类。
   经过以上步骤得到如下的结果。当然是没有任何代码的。
     
  
接下来先检查Student.hbm.xml中的

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Model.Entities.Student,Model" table="Student" lazy="true">
    <id name="StudentId" column="StudentId" type="int">
      <generator class="native" />
    </id>
    <property type="string" length="40" name="StudentName" column="[StudentName]" />
    <property type="string" length="20" name="StudentPassword" column="[StudentPassword]" />
    <property type="string" length="40" name="EmailAddress" column="[EmailAddress]" />
    <property type="DateTime" name="DateCreated" column="[DateCreated]" />
  </class>
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Model.Entities.Student,Model" table="Student" lazy="true">

这里要注意是2.2,不是2.0。
其次是在下面的Model.Entities.Student,Model这里前者是实体,后者是程序集。这个当然只有初学者会有点疑问。

接下来是增加应用程序配置文件信息,首先是在App.config里面加上

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings>
        <!--<add name="Connection String" connectionString="Data Source=YeanJay;User Id=YeanJay;Password=YeanJay;Persist Security Info=true" providerName="System.Data.OracleClient"/>-->
        <add name="Connection String" connectionString="Data Source=YeanJay;Database=NHibernate;uid=YeanJay;pwd=YeanJay" providerName="System.Data.SqlClient"/>

</connectionStrings>
</configuration>

这里只是增加了数据库链接字符串,注意:这里的Connection String在NHibernate的配置文件中要用到,所以要保持一致。这里如果要将数据库从MSSql迁移到Oracle,那么我们只要将上面的注释去掉,然后将下面这句MSSQL的注释掉就可以了。
然后来看NHibernate的两个配置文件:NHibernateMSSQL.config和NHibernateOracle.config
 >NHibernateMSSQL.config:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
    <session-factory name="northwind">
        <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
        <property name="connection.connection_string_name">Connection String</property>
        <property name="connection.isolation">ReadCommitted</property>
         <!-- Mapping Files -->
        <mapping assembly="Model"/>
    </session-factory>
</hibernate-configuration>

>NHibernateOracle.config

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
    <session-factory name="northwind">
        <property name="dialect">NHibernate.Dialect.Oracle10Dialect</property>
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="connection.driver_class">NHibernate.Driver.OracleClientDriver</property>
        <property name="connection.connection_string_name">Connection String</property>
        <property name="connection.isolation">ReadCommitted</property>

<!-- Mapping Files -->
        <mapping assembly="Model"/>
    </session-factory>
</hibernate-configuration>

这里有一个<mapping assembly="Model">就是之前提到的那个映射实体类的那个程序集。
在开始编写代码之前,我们需要将一些需要的引用添加到每个工程里面:
DAL:引用Model项目和NHibernate.dll
Model:引用Iesi.Collections.dll和NHibernate.dll
在WinForm项目中:根据YJingLee的例子是引用DAL,Model这两个项目,和NHibernate.dll,暂时我们也这么引用。
现在开始编写代码:
SessionManager.cs类:

Code

这里的Configuration ctg = new Configuration().Configure("./NHibernateMSSQL.config");的方式在NHibernate的灵活配置 有讲到。
     当然这里的"./NHibernateMSSQL.config"在实际生产中一般不要写到这里来,一般是从配置文件中读取过来。这里为了方便,我就直接写在这里了。
     这里我也没有去关心这个线程安全不安全的问题了。见谅!

SessionManager.cs类:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NHibernate;
using Model.Entities;
//using NHibernate.Cfg;

namespace DAL {
   public class GetStudent {
       private ISession _session;

public ISession Session {
           set { _session = value; }
       }

public GetStudent(ISession session) {
           _session = session;
       }

public Student GetStudentById(int studentId) {
           return _session.Get<Student>(studentId);
       }
   }
}

Form.cs 代码:

Code

OK,开始执行。
叮!第一个错误跳出来:
“NHibernate.Cfg.Configuration”的类型初始值设定项引发异常。
查看详细信息:
未能加载文件或程序集“log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821”或它的某一个依赖项。
系统找不到指定的文件。

第一次想到在DAL中加入log4net.dll(这个dll在下载过来的最新版的NHibernate的bin文件夹下有的)。没想到问题依然存在,那好,就先撤销在DAL中的log4net,然后直接到Winform下添加log4net结果错误消失了。但是第二个错误 咚!又出来了!

The following types may not be used as proxies:

Model.Entities.Course:method get_IsDeleted should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Course: method set_IsDeleted should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Course: method get_IsChanged should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Course: method set_IsChanged should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Course: method Clone should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.StudentCourse: method get_IsDeleted should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.StudentCourse: method set_IsDeleted should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.StudentCourse: method get_IsChanged should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.StudentCourse: method set_IsChanged should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.StudentCourse: method Clone should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Student: method get_IsDeleted should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Student: method set_IsDeleted should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Student: method get_IsChanged should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Student: method set_IsChanged should be ‘public/protected virtual‘ or ‘protected internal virtual‘

Model.Entities.Student: method Clone should be ‘public/protected virtual‘ or ‘protected internal virtual‘

这个就是在老赵今天发的我对NHibernate的感受(2):何必到处都virtual的提到的到处都是Virtual了,在MyGeneration生成的映射文件中,有些方法并不是Virtural的,所以会出现编译通过,但是执行出错的情况。
   解决方案,当然是在每个方法和属性上面加上Virtual了。

处理完这个错误,当然还是没有那么顺利就过关啦,第三个错误依旧报来!

这也就是需要注意的另外一点:在2.1版本中的NHibernate中需要在NHibernate配置文件中加入
<property name=‘proxyfactory.factory_class‘>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
这样一节,这个来源于YJingLee博客里的一个答复。

加入以后,继续编译,执行。叮叮!!又来一错误:

“NHibernate.ByteCode.Castle.ProxyFactory”的类型初始值设定项引发异常。
查看详细信息:
未能加载文件或程序集“Castle.DynamicProxy2, Version=2.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc”或它的某一个依赖项。
系统找不到指定的文件。
当然应该也是2.1的版本的缘故咯。然后继续到源码文件夹下的bin目录下找到这个DLL,添加。具体信息可以参考这里
 继续编译执行。继续出错:

未能加载文件或程序集“Castle.Core, Version=1.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc”或它的某一个依赖项。系统找不到指定的文件。

神呐,继续找问题,继续添加引用。
继续编译。现在发现在Winform下的引用已经很多了。都是NHibernate2.1执行的依赖项。
全部添加完,相变的引用如下:

这些引用都可以在NHibernate源码的bin目录下可以找到。
接下来编译。测试通过!!!
执行的界面如下:

数据库执行脚本下载项目源代码下载

时间: 2024-10-05 22:59:02

我的NHibernate曲折之行的相关文章

Query Object--查询对象模式(下)

回顾 上一篇对模式进行了介绍,并基于ADO.NET进行了实现,虽然现在ORM框架越来越流行,但是很多中小型的公司仍然是使用ADO.NET来进行数据库操作的,随着项目的需求不断增加,业务不断变化,ADO.NET的实现方式,会使原先简单的单表操作变得尤为复杂,特别是数据库表发生改变的情况下,无法像ORM框架那样,通过修改映射来达到统一的修改,需要靠程序员检查每一段相关的SQL来排查错误,这是非常麻烦的. 不管什么样的框架,使用起来不简单不易用的话,那么就没有设计的必要了. 因此今次的文章将会基于OR

我的NHibernate之行(二):增删改

上一篇博客,通过一个小Demo来大致的介绍了NHibernate的使用过程.使用NHibernate,最根本还是"CRUD"(增删改查).我们常常所说的一个工作单元,通常是执行1个或多个操作,对这些操作要么提交要么放弃/回滚.如果只查询数据,不改变它的值,就不需要提交(或者回滚)到数据库.对于查询操作,内容比较多,这次就不涉及.本文仅仅介绍一下增删改操作. 注意:这节,我们在上一节源代码的基础上,在数据访问层中新建SessionCRUD.cs类用于编写操作方法,在测试层新建一CRUDF

我的NHibernate之行(一):NHibernate五部曲

NHibernate是一个面向.NET环境的对象/关系数据库映射工具.对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去.--百度百科 简介 从网上找到下面的一张图,自认为这张图相当好: 简单的说ORM,能够达到这样一种效果:我们不用去知道数据库(R)的内容,系统根据M,通过对对象(O)的操作,自动完成访问数据库.例如要完成"根据ID查询",我们对对象使用了Get<

工欲善其事,必先利其器——NHibernate

工欲善其事,必先利其器——NHibernate Orchard中用到了许多开源的技术,NHibernate也是其中之一. 下面就来谈一下NHibernate的使用. 熟悉java的人应该清楚,NHibernate来源于Hibernate. 以下为网上转载: 前言 这篇文章出自于我尝试学习使用Nhiberbnate的挫败感.我发现好像Nhibernate全部的介绍材料不是很模糊就是太详细.我所需要的就是一个简单直接的教程,能让我尽快对NHibernate熟悉起来.我从来没有找到.幸运的是,这篇文章

NHibernate变的简单

前言 这篇文章出自于我尝试学习使用Nhiberbnate的挫败感.我发现好像Nhibernate全部的介绍材料不是很模糊就是太详细.我所需要的就是一个简单直接的教程,能让我尽快对NHibernate熟悉起来.我从来没有找到.幸运的是,这篇文章将会满足别人的这些需求. 这篇文章有些长,但是我鼓励你以你的方式来阅读.NHibernate是一个复杂的程序,是一个绵延曲折的学习过程.这篇文章将为你踏平曲折,从几天或是几周缩短到几个小时. 问题 NHibernate目的是解决一个众所周知的问题,对象持久代

NHibernate框架与BLL+DAL+Model+Controller+UI 多层架构十分相似--『Spring.NET+NHibernate+泛型』概述、知识准备及介绍(一)

原文://http://blog.csdn.net/wb09100310/article/details/47271555 1. 概述 搭建了Spring.NET+NHibernate的一个数据查询系统.之前没用过这两个框架,也算是先学现买,在做完设计之 后花了一周搭建成功了.其中,还加上了我的一些改进思想,把DAO和BLL之中相似且常用的增删改查通过泛型T抽象到了DAO和BLL的父类中,其DAO 和BLL子类只需继承父类就拥有了这些方法.和之前的一个数据库表(视图)对应一个实体,一个实体对应一

记一次曲折的渗透

那是一个无聊的下午,我还在折腾我的ettercap,接到基友的呼唤,要用我手上的资源搞个对象,我仔细想了下,如果在对方的局域网内的话,这事就显的好办多了,因为要用139.445这是个校园局域网.于是乎我就开始搞学校的站,因为在校站的服务器上就和这家伙接壤了~所以就引出了这次非常和谐各种曲折的渗透经历啊:) 1.目标发现 想着随便搞个站就行,也没有特定的目标,果断google hacking了一下.手工判断了下找到的几个链接,目测其中一个是mssql,放到havij里一试便知了.人品确实不错,是s

NHibernate官方文档中文版--基础ORM(Basic O/R Mapping)

映射声明 对象/关系映射在XML文件中配置.mapping文件这样设计是为了使它可读性强并且可修改.mapping语言是以对象为中心,意味着mapping是围绕着持久化类声明来建立的,而不是围绕数据表. 要注意的是,尽管很多NHibernate使用者选择手动定义XML文件,但是仍然有很多工具可以用来生成mapping文件,包括NHibernate.Mapping.Attributes 库和各种各样基于模板的代码生成工具(CodeSmith, MyGeneration). 让我们用一个mappin

[NHibernate]存储过程的使用(三)

目录 写在前面 文档与系列文章 查询 总结 写在前面 前面的文章介绍了在nhibernate中使用存储过程进行增删改的操作,当然查询也是可以的,在nhibernate中也可以执行任意的存储过程.本篇文章将介绍如何使用查询的存储过程的方式. 文档与系列文章 [Nhibernate]体系结构 [NHibernate]ISessionFactory配置 [NHibernate]持久化类(Persistent Classes) [NHibernate]O/R Mapping基础 [NHibernate]