|
前言
这篇文章出自于我尝试学习使用Nhiberbnate的挫败感。我发现好像Nhibernate全部的介绍材料不是很模糊就是太详细。我所需要的就是一个简单直接的教程,能让我尽快对NHibernate熟悉起来。我从来没有找到。幸运的是,这篇文章将会满足别人的这些需求。
这篇文章有些长,但是我鼓励你以你的方式来阅读。NHibernate是一个复杂的程序,是一个绵延曲折的学习过程。这篇文章将为你踏平曲折,从几天或是几周缩短到几个小时。
问题
NHibernate目的是解决一个众所周知的问题,对象持久代码在开发过程中的瓶颈问题。很多文章表明:1/4到1/3的程序代码是关于对象持久化,从数据库中读取数据,和将数据写回数据库。代码是重复的,耗费时间的,还有很多琐碎的代码要写。
对于这个问题,有很多解决方案是可用的。代码生成可以在几秒钟生成数据访问代码。但是如果业务模型改变,这些代码需要重新生成。"对象关系映射"(ORMs)使用了一种新的方式,像NHibernate。他们管理数据访问更加透明,提供了很多简洁的API,可以使用一辆行代码来实现加载和保存整个对象。
介绍NHibernate
NHibernate是一个持久化引擎框架。它从数据库中加载业务对象,以及将这些对象的变化更新到数据库中。从文章上面可以看出,它可以只使用一两行代码实现业务对象的加载和保存。
NHibernate使用映射文件来引导从数据库数据到业务对象的转换。还有一种方法,你可以使用类的特性和属性来替代映射文件。为了让事情尽量简单,我们在这篇文章中将使用映射文件,而不是使用类特性。另外,映射文件能够很清晰的将业务逻辑和持久化代码分开。
好了,我们只需要在程序中添加几行代码,和为每一个映射文件创建持久化类,而且NHibernate可以照顾到所有的数据库操作。真不知道使用NHibernate将为我们节省多少开发时间。
记住在.NET环境下,NHibernate并不是唯一的ORM框架。有许多商业的和开源的产品可以提供这样的服务。NHibernate是其中最流行的,主要是因为他遗传自强大的Hibernate,一个Java环境下非常流行的ORM框架。另外,微软也为ADO.NET提供了"Entity Framework",来提供ORM服务。但是,这个产品已经延迟,好长时间已经没有再释放了。
安装NHibernate
使用NHibernate的第一步就是下载NHibernate和Log4NET(一个开源的日志记录程序,NHibernate使用它来记录错误和警告),NHibernate包含了Log4NET最新的版本,你也可以下载整个Log4NET安装包,这里是下载地址:
NHibernate不是直接需要Log4NET,可是在调试期间它的自动记录日志功能非常有用。
现在开始
在这篇文章中,我将使用一个简单的示例程序,而不是解说如何使用NHibernate来进行数据访问。这是一个控制台应用程序,通过消除UI代码让程序变的更加简单。这个程序将创建很多个业务对象,来使用NHibernate来对他们进行持久化,然后将他们从数据库中读取出来。
为了程序运行起来,你需要做一下几个事情:
- 为陈旭添加NHibernate和Log4NET的程序集引用
- 为程序添加数据库
- 修改数据库连接字符串
这个示例程序引用NHibernate和Log4NET。这些应用应该被你的机器识别,如果你的NHibernate和log4NET安装在默认的目录里。如果这些引用不被识别,你可以分别使用NHibernate.dll和Log4NET.dll来替换引用位置。这些DLL文件可以在NHibernate的安装目录中找到。
这个示例程序是按照SQL Server Express 2005来配置的,数据库文件(NhibernateSimpleDemo.mdf和NhibernateSimpleDemo.ldf)已经打包在压缩文件里。你可以将数据库搭在你机器的SQL Server上。
最后,数据库的连接字符串配置在App.config文件中,默认你使用的是SQL Server数据库。你可以自己根据自己机器SQL Server的版本,来修改数据库的连接字符串。
业务模型
这里有两种方法使用NHibernate创建应用程序。第一种是“以数据为中心”的方法,它从数据模型和创建业务对象开始。第二种是“以对象为中心”的方法,从业务模型和创建数据库来持久化这个模型开始。这个示例程序使用以对象为中心的方式。
这里示例中的业务模型:
这个模型表现了一个订单系统的框架,这个模型是不完整的,这里只是使用了几个类来解说使用NHibernate对象持久化。显然这个模型的设计不能代表最佳实践,但是用来展示NHibernate是怎样工作的已经足够应付了。
此文将使用这个模型来解说使用NHibernate进行对象持久化的几个概念。
- 处理简单属性
- 处理Components
- 处理one-to-many
- 处理many-to-one
- 处理many-to-many
此文不会涉及高级主题,像继承。
这个模型由5个类组成,其中的4个是要持久化的类,非持久化类OraderSystem当做这个对象模型的宿主。我们将会在程序运行时初始化OrderSystem对象,然后我们将加载其他的对象到OrderSystem中来。
OrderSystem.Customers属性拥有销售者的客户列表,Customers可以通过CustomerID来访问,每一个Customer对象拥有一个ID,name,和address、一个序列的orders。address将被包成一个单独的Address类中。
Order类包含了一个订单的ID,时间,顾客信息,和许多购买的产品信息。
Product类包含ID,名称。
请注意我们只注重NHibernate是怎么工作的,程序初始化时,Product对象将被实例化放入OrderSystem.Catalog属性中,当一个订单被创建时,Product对象引用将不复制到Order.OrderItems属性中。
NHibernate一个强大的特点就是不需要为业务类实现特别的接口。事实上,业务对象通常不会担心被持久化机制来加载和保存他们。NHibernate使用的映射数据保存在分离的XML文件中。
数据库
数据库和对象模型并不是完全匹配,对象模型中包含一个Address类,但是数据库中并没有与之对应的表。数据库中有OrderItems表,但是对象模型中并没有与之对应的持久化的类。这里的不匹配并不是故意的,我们想展示的NHibernate其中的一个概念就是这里并不需要数据库中的表跟类是一一对应的。
这里是为什么不完全匹配的原因:
- Address类并不能代表业务模型的一个实体,相反,它只代表一个实体的值,在这个示例中,代表Customer.Address 属性,我们将Address分离一个单独的类,这样我们可以解说什么叫NHibernate使用“Component mapping”。
- OrderItems表是多对多关系中Orders和Products的连接表,这样也不能代表对象模型中的一个实体。
Customer表包含了一个普通Customer信息的骨架,包含Customer的Address信息。最佳实践不会像我们这样,将会把Address分离在一个单独的表中。我们把Address信息保存在Customer表中,这样我们可以解释什么是NHibernate使用‘Components’类,而不使用Address自己的表,我们将在下面讨论Components的详细用法。
Orders表只包含一个订单的最简单的信息,只有ID,时间,和CustomerID。Orders和Customers之间的关系通过一个外键orders.ustomerID 列对应 Customer.ID列。
所有的订单学要一个多对多的关系(每一条订单包含很多条商品信息,每一条商品信息又被包含在很多订单里),所以我们需要OrderItems表来当作中介,简单的连接Order编号和Product编号。
这个数据库并不是一个最佳实践,它所包含的信息仅仅用来展示NHibernate是怎样工作的。
映射业务模型
许多介绍NHibernate的文章都是以配置文件开始的,但是从另一个地方开始:映射类。映射是NHibernate的核心,而且配置也给初学者一个很大的绊脚石。当我们讨论完映射,我们再回来介绍NHibernate的配置部分。
映射简单的指定哪一个表对应哪一个类。我们把映射的类对应的表叫这个类的“映射表”。
我们在上面就已经说了,Nhibernate不需要特定的接口或是特定的代码写在要映射的类里。但是它需要被声明成Virtual,这样可以在需要的时候创建代理。NHibernate文档里讨论了为什么这样,现在我们把所有业务模型中的类声明成Virtual。
映射可以同过分离的XML文件实现,也可以通过在类属性上添加特性来实现。被用于映射的XML文件可以在任何一个项目里引用。为了简单,我们将展示其中一个方法:通过XML文件映射,映射文件需要被编译成程序集的嵌入式资源。
你可以映射很多类在同一个映射文件中,但是通常都会为每一个类创建一个映射文件。这样可以保持映射文件的短小,而且容易阅读。
开始我们映射实验之前,先让我们看看Customer.hbm.xml文件。hbm.xml后缀的文件是NHibernate标准的映射文件的后缀。我们把映射文件放在Model文件下,但是我们可以把他们放在项目的任何一个地方。最关键的一点是将文件的 BuildAction 属性设置为 Embedden Resource(嵌入式资源)。这个设置将会把映射文件编译到程序集里,这样把他们从程序中脱离出来。
映射文件都是标准的格式:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="NHibernateSimpleDemo"
assembly="NHibernateSimpleDemo">
NET技术:NHibernate 变的简单,转载需保留来源!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。