NHibernate in Action(第一章1.1)
第一章 .NET中的对象/关系持久化
本章包含:
.NET持久化与关系数据库
.NET程序的分层
.NET持久化分层的方法
NHibernate如何实现关系数据库中的持久化对象
高级持久化特性
软件开发是一个最新技术与技巧时常更新的学科。作为一个软件开发人员,我们有大量的工具和实践可供选择,选择一个适当的工具往往可以成就一个项目或破坏一个项目。其中一个关键性的选择就是---如何处理持久层的数据---或者简单的说如何加载和保存数据。
几乎有无数可供选择的方法。你可以以二进制形式或者文本形式存储到硬盘中。你也可以选择项CSV,XML,JSON,YAML或者SOAP又或者发明你自己的格式来存储数据。同样的,你也可以通过网络将数据发送到另外一个应用程序或服务,如关系数据库,活动目录服务器,或者一个消息队列。你甚至可能需要将数据存储到不同的地方或者将上述的方法合并到一个应用程序中。
现在你可能会发现,管理持久层数据是一个多么棘手的问题。关系数据库非常流行,但是各种选择,疑问和选项仍然是你日常工作中需要面对的。例如,应该使用DataSet还是DataReader比较合适?是否应该使用存储过程?是自己手写SQL代码还是让你的工具自动生成?是否应该严格定义Dataset?是否应该手写包含所有类的领域模型?如果是这样,那么你应该如何加载和保存数据到数据库?你用过代码生成吗?一大堆的问题还会紧接而来。
这个问题不只是在.NET中出现,所有开发人员经常是在努力解决这个问题,而且还持续了很多年了。
但是,其中有一个实践方法得到了广泛的认同:对象关系映射(ORM)。经过了许多年,出现了很多类库及工具来帮助开发者构建ORM应用程序。NHibernate就是其中之一----一个成熟又强大的.NET对象关系映射工具。
NHibernate是非常流行的Hibernate类库中的.NET接口。NHibernate的目标是提供一个解决关系数据库和领域模型类之间数据持久化问题的解决方案,让你可以自由的处理业务逻辑。该书涵盖了NHibernate的基础和高级应用。它同时推荐一些最佳实践方法,用于使用NHibernate开发新应用程序。
在你开始了解NHibernate之前,有必要先了解一下什么是持久化已经.NET Framework实现该功能的几种方法。这章讲介绍为什么需要使用像NHibernate这样的工具。
我需要阅读所有的这些背景资料吗?
不需要,如果你想马上尝试使用NHibernate,你可以跳转到第二章,开始编写一个简单的NHibernate应用程序。没有阅读第一章不会影响你阅读第二章,但是如果你对.NET的持久化不太了解我们推荐你先阅读这一章。同时你也可以了解到一个重要的概念:工作单元。如果你对这个讨论有兴趣,那么你可以接着阅读第一章,获得更多关于.NET持久化的支持,然后再继续阅读。
首先,我们定义了.NET应用程序中持久化的概念。紧接着我们举例说明如何使用.NET Framework传统的持久化工具来实施.net应用程序。你会发现当使用关系数据库和像.net这样面向对象框架时常遇到的一些困难,以及一些流行的持久化处理方法是如何解决这些问题的。同样的,这些问题被称为面向对象和关系数据库的范式匹配。接着介绍NHibernate的实现方法和讨论它的一些优点。紧接着,我们的深入设计一些复杂的持久层来实现一个像NHibernate必不可少的工具。最后,我们给ORM做了个定义和讨论为什么我们需要使用它。到了文章的结尾,你应该对使用NHibernate带来的好处有一个清晰的理解。
1.1什么是持久化?
持久化是应用程序开发的基础关切。如果你有软件开发的一些经验,你应该已经处理过这方面的问题。几乎所有的程序都需要持久化数据。你使用持久化来保存数据即使程序没有运行。
为了说明,我们假设你需要建立一个应用程序让你的用户可以储存他们公司的电话号码,联系方式,同时他们可以随时的查询他们需要的东西。除非你让你的用户一直运行着程序,否则你会意识到你的应用程序必须将这些联系方式保存在某些地方。这样你就面临着一个持久化的选择:你必须选择将要使用什么持久化机制。你有很多个持久化数据到各个地方的方式,最简单的就是文本文件。更多时候,你可能会选择关系数据库,因为这样的数据库被广泛的理解并提供了强大的可靠存储和检索数据。
1.1.1 关系数据库
你可能使用了诸如MSSQL,MySQL 或者Oracle这样的关系数据库。如果你没有用过,请看附录A。大部分开发者每天都在使用关系数据库,它们广大开发者接受并认为是一个强大和稳定的数据管理解决方案。
一个关系数据库管理系统不是仅限于.NET语言的,同时也没必要仅限于某个应用程序。你可以有好几个应用程序同时使用一个数据库,可能有些是用.NET写的,有写实JAVA或者Ruby等待。关系技术提供一种应用程序之间数据共享的方式。就算是一个系统里面的不同构件都可以单独访问数据库(例如一个报表引擎和日志组件)。
关系技术是许多不关联系统和技术平台的共性。关系数据模型通常是用于描述企业级的业务对象:一个业务对象需要存储大量的信息,例如:客户信息,账号和产品信息(业务对象),关系数据库通常被用于存储他们定义的这些对象。这让关系数据库成为IT领域的一个重要部分。
RDBMS的有基于SQL的应用程序编程接口(API)。因此,今天的关系数据库产品被称为SQL数据库管理系统,或者是我们谈到了具体的系统:SQL数据库。
1.1.2 理解SQL
像其它.NET数据库开发者一样,充分了解关系数据库和SQL是使用NHibernate的先决条件。你可以使用SQL来调优你的NHibernate应用程序。NHibernate自动化实现了许多重复的编码工作,但是如果你想更好利用现代SQL数据库的全部功能,那么你的持久化技术知识必须超越NHibernate。请记住,我们的基本目标是良好的:有效的管理持久化数据。
如果你觉得你需要提高自己的SQL技巧,那么请阅读Dan Tow【Tow 2003】的《SQL Tunning》和Anthony Molinaro【Mol 2005】写的《SQL Cookbook》。Joe Celko也写了一本关于SQL高级技术的很好的书。如果想有更好的理论背景,可以考虑阅读《An Introduction to Database Systems》【2004年】。
1.1.3 在.NET应用程序中使用SQL
.NET提供了许多工具和选择来实现应用程序与数据库交互。你可能已经使用过Visual Studio开发环境,利用它的拖拽功能,只要点击几下鼠标,你就可以创建一个数据库连接,执行查询和在屏幕上显示可编辑的数据。这样的方法对于简单的应用非常适合,但是这样的方法对于大规模、复杂的系统并不适用。
你可以选择使用SqlCommand对象和手动写和执行SQL来建立DataSets其中之一。这样做很快就变得非常繁琐:你希望能够稍微高层次的抽象,让你更专注于业务问题而不是考虑数据访问问题。如果你对学习更广泛的数据访问方法和测试,那么可以考虑阅读Martin Fowler的《Patterns of Enterprise Application Architecture 》【FOwler 2003】,本书更深入的解释了这方面的技术。
在所有的方案中,我们采取的方法是编写类---或者是可以加载或保存到数据库的业务实体。跟Dataset不一样的是,这些类不是用于与关系数据库结构进行映射的(比如行和列),他们是用于解决手头上的业务问题。总而言之,这样的类通常被描述为对象关系域模型。
1.1.4 面向对象应用程序中的持久化
在一个面向对象应用程序中,持久层允许对象可以在进程或者创建他的应用程序之外存活。这个对象的状态将被存储到硬盘中,同时在未来某个时间内将被重新创建。
这种应用不仅限于当个对象---整个对象关系图都可以持久化也可以重新创建。大部分对象并不是持久性的,一个暂时的对象是一个具有短暂生命周期,并且被实例化的对象具有一定的生命界限。最简单的实例就是web控件对象,它只是在渲染到屏幕之前短暂的存在于内存中,并且在此之后就从内存中清除。几乎所有.NET应用程序都同时包含了持久性和暂时性对象,因此适用一个子系统来管理持久化对象就成为一件有意义的事情。
现代关系数据库提供了一个结构用于表示持久化数据,包括排序,搜索和数据分组。数据库管理系统用于管理向并发和数据完整性。他们用于处理不用用户和应用程序间的数据共享。数据库管理系统同时提供了数据级的安全。当我们在本书中讨论持久性的时候,我们也考虑下面这些问题:
-
数据存储、组织和检索结构化数据
-
并发性和数据完整性
-
数据共享
特别的,我们在使用域模型的面向对象应用程序中考虑了这些问题。一个具有领域模型的应用程序并不与表格类型的表示方式表示业务实体(使用DataSets);应用程序具有它独有的,面向对象模型的业务实体。如果数据库中有ITEM和BID这两个表,那么.NET应用程序将定义Item和Bid两个类,而不是使用DataTable来表示。
因此,业务逻辑与面向对象域模型和运行时实现的对象关系图进行交互,而不是直接与DataTables中的行和列交互。业务逻辑并不在数据库执行(作为一个SQL存储过程);它全部是有.NET完成。这可以使得业务逻辑使用高级的面向对象概念,例如:继承和多台。例如,你可以使用一些知名的设计模式如:策略模式,中介者模式或组合模式。【GOF1995】,这些都基于多台函数的调用。
现在,有个提示:并不是所有的.NET应用程序都按照这这方式来设计,额部需要这样。简单的应用程序可能不适用领域模型会更好。SQL和ADO.NET对于表格类数据是非常有用的,DataSet让CRUD操作变得更简单。使用表格形式的持久层表示方式使得程序更加直接和更好理解。
但是对于具有复杂业务逻辑的应用程序,领域模型可以帮助显著的提高代码的重用和可维护性。在本书中,我们主要专注于程序的领域魔心,因为NHibernate和ORM通常都是与这类型的应用程序最相关的。
现在理解一个领域模型如何适应一个大的软件系统蓝图是非常有用的。为了解释这一点,让我们来回顾一下分层架构。
1.1.5 持久化与分层设计
现在有很多,如果不是大部分,系统都使用了分层架构设计,NHibernate能很好的实现这个架构,那么,什么事分层架构呢?
分层架构将一个系统分层了几个组,每一组包含了解决某一领域问题的代码。这些组被称为层。例如,用户接口层(也叫做表示层)可能包含着所有页面显示和处理用户输入的程序代码。其中分层结果的一个主要好处就是你可以经常针对某个层进行修改而不会影响到其他层,从而使系统不那么脆弱和更易于维护。
分层架构需要遵循以下几个规定:
-
层与层之间自上而下进行通信,一个层只依赖于他底下的那一层
-
一个层除了它之下的那一层,并不知道其它层的存在
业务应用程序使用一个流行,且被证实是高级的程序架构,它有三个层次组成,表示层、业务层和持久层。如图1.1
![](http://farm5.static.flickr.com/4068/4342049089_e7a06217a9_o.jpg)
让我们来仔细研究图片中的层和其它元素:
-
表示层---用户接口逻辑是在最顶端的。在web应用程序中,这一层中的代码的职责是生成一个页面或节目,搜集用户输入信息和控制导航。
-
业务逻辑层---这一层的样式在不同的之间具有很大的变化。但是业务层还是被广泛认为适用于实现业务规定或者用户可理解的问题域的一部分的系统需求。在一些系统中,该层具有它自己内部的业务域实体表示方式。在一些其它系统中,它将重用在持久层中定义的实体。我们将在第三章再次探讨这个问题。
-
持久层---持久层是一组类或者组件用于在一个或多个数据存储媒介中保存系统数据或者检索数据。这一层定义了业务领域实体与数据库的映射关系。所以当你听到NHibernate主要用于该层时不必感到惊讶。
-
数据库---数据库存在于.NET应用程序之外。事实上,持久层已经表示了数据库的状态。如果使用了SQL数据库,则包含了一些关系模型以及一些可能用到的存储过程。
-
Helper/Utility类---每个系统都有一套用于支撑其它层的基础帮助类和公共类:例如,UI widgets,消息类,异常类和日志类。这些基础元素并不是层次结构中的一层,因为他们不遵循层次架构中层次之间依赖关系的规定。
所有程序都需要三层吗?
虽然三层架构在许多系统中非常普遍和有用,但是并不是所有.NET应用程序都需要设计成这样,也不一定要。简单的应用程序最好还是不要使用复杂的对象。SQL和ADO.NET API就可以处理这些单纯的表格数据,而且ADO.NET的DATASET让这些基本操作变得更加容易。使用表格形式的表示方式使持久化数据变得更直观和更好理解。
请记住分层次对于大型复杂系统是非常有用的,同时也经常使简单的.NET应用杀掉。对于那些简单的应用,你可以选择将代码放到一个地方。你可以将业务逻辑放到你的web/windows程序中的后台代码中,而不是将业务逻辑和数据库访问功能完全的分成不同的层次。像Visual Studio .NET可以很容易的帮你构建这样的系统。但是请注意,这种方法可能很快会出现问题代码,随着程序的增长,你必须添加越来越多的代码都每个表单和页面中,接着,维护工作将会变得越来越难。此外,数据库的改变很容易的让你的程序down掉,而且查找和修复这些问题可能需要大量时间且是痛苦的。