CSDN博客

img colayungnew

应用程序设计指南:从 N 层到 .NET

发表于2004/10/14 15:12:00  1135人阅读

分类: MSDN

 

摘要:讨论用于 Microsoft .NET 的应用程序设计以及所需的更改:复习从使用 Microsoft Windows DNA 构建 N 层应用程序中学到的体系结构知识,如何在利用 Microsoft .NET 框架构建应用程序过程中运用这些知识,以及对使用 XML Web 服务的应用程序用在体系结构方面时的建议。(11 页打印页)

简介

如今,N 层应用程序已经成为构建企业软件的标准。对于大多数人来说,N 层应用程序就是被分成多个独立的逻辑部分的应用程序。最常见的选择是分为三个部分:表示、业务逻辑和数据,当然还可能存在其他的划分方法。N 层应用程序最初是为了解决与传统的客户端/服务器应用程序相关的问题而出现的,但是,随着 Web 时代的到来,这一体系结构开始成为新开发项目的主流。

Microsoft Windows? DNA 技术已成为 N 层应用程序的非常成功的基础。Microsoft .NET 框架也为构建 N 层应用程序提供了坚实的平台。然而,.NET 所带来的变化使体系结构设计人员应当重新考虑他们在 Windows DNA 领域中所学的有关设计 N 层应用程序的某些知识。更重要的是,对内置于 .NET 框架的 XML Web 服务 的基本支持允许开发人员构建突破传统 N 层方法的新应用程序。要了解如何更好地构建 .NET 应用程序的体系结构,您需要了解这一新领域中发生了哪些变化,以及如何充分利用这些变化。

本文将对这些问题进行讨论。首先回顾一下在使用 Windows DNA 构建 N 层应用程序中学到的关键体系结构知识。然后,再按同一顺序将这些知识应用到使用 .NET 框架构建应用程序的过程中,从而对它们进行检验。最后一部分对使用 XML Web 服务 的应用程序的体系结构提供了一些建议。

返回页首

Windows DNA 环境

将应用程序分解成多个逻辑部分是很有用的。将一个大软件分成几个小的部分会更利于软件的构建、重复利用和修改。对适应不同的技术或不同的业务组织也很有帮助。同时,还有一些综合因素需要考虑。虽然模块化和重复使用性很有效,但它们可能会导致应用程序不能象使用其他方法那样安全、易管理和快速。本节将回顾一些从使用 Windows DNA 技术构建 N 层应用程序的普遍经验中所获得的基本体系结构知识。

编写业务逻辑

Windows DNA 应用程序通常使用以下三种实现方式中的一种或多种方式来实现其业务逻辑:

ASP 页

COM 组件,可能使用 COM+ 提供的其他服务

DBMS 中运行的存储过程

一般来讲,在 ASP 页中编写过多的业务逻辑并不是一个好办法。因为必须使用简单的语言(例如,Microsoft Visual Basic? Script (VBScript)),而且每次执行时都要解释代码,这会对性能造成影响。而且 ASP 页中的代码不好维护,主要是因为业务逻辑通常与创建用户界面的表示代码混合在一起。

鉴于这种情况,建议在编写中间层业务逻辑时,将业务逻辑当作 COM 对象来实现。这种方法比编写纯粹的 ASP 应用程序要稍微复杂一点,但是可以使用全功能语言来生成编译好的可执行文件,因此其结果要快得多。将业务逻辑包装在 COM 对象中还可以将此代码与包含在 ASP 页中的表示代码完全分隔开来,从而使应用程序更易于维护。

COM 到 COM+,其体系结构相差无几。但是,正如许多 Windows DNA 体系结构设计人员所了解的,除非真正需要,否则不应使用 COM+ 提供的核心服务,如事务、实时 (JIT) 激活、基于角色的安全性和线程服务等。使用其他开发平台提供的 COM+ 或类似服务自然会导致应用程序速度更慢、更复杂。只有在以下情况下使用 COM+ 才有意义:

需要跨越不同资源管理器(例如,Microsoft SQL Server(TM) 和 Oracle)的分布式事务。

应用程序可以有效地利用基于角色的安全性。

可以增强 Microsoft Visual Basic? 6.0 的线程特性。

JIT 激活能够提高性能;浏览器客户端很少出现这种情况,因为 ASP 页是通过 JIT 有效激活的。

COM+ 的配置优势大大简化了应用程序的部署。

编写业务逻辑的第三种方式是,创建一些作为存储过程在数据库管理系统 (DBMS) 中运行的代码。尽管使用存储过程的主要原因是将数据库架构的详细信息与业务逻辑分隔开以简化代码的管理和提高安全性,但代码与数据如此接近也有助于优化性能。那些必须独立于 DBMS 的应用程序(例如由独立的软件供应商创建的应用程序)通常要避免使用这种方法,因为它会将应用程序锁定到某个特定的数据库系统中。存储过程的编写和调试可能会比 COM 对象的编写和调试难,而且此方法会减少重复使用代码的机会,这是因为 COM 对象通常比存储过程更易于重复使用。但是大多数自定义应用程序仍然连接到最初创建它们的 DBMS 上,因此使用存储过程的性能优势还是很大的。鉴于这种情况,那些必须尽可能运行良好的 Windows DNA 应用程序通常对部分或全部的业务逻辑都使用存储过程。

构建客户端

Windows DNA 既支持用 Visual Basic 等语言编写的本地 Windows 客户端,也支持浏览器客户端。浏览器客户端的局限性较大,尤其同时将 Microsoft Internet Explorer 和 Netscape 作为浏览器时。因此,应用程序通常同时拥有浏览器客户端和本地 Windows 客户端。浏览器客户端提供的界面很有限,但用它可以方便地访问 Internet,而 Windows 客户端能提供全功能的界面。使用可下载的 Microsoft ActiveX? 控件可以创建更复杂的浏览器界面,但必须确保浏览器是 Internet Explorer,并且用户愿意信任应用程序的创建者。

管理浏览器应用程序中的状态

ASP 应用程序可以使用几个不同的机制来维护服务器上客户端请求之间的信息。但是 Windows DNA 中有一条严格的规则,如果应用程序在两台或多台机器之间平衡负载,则绝对不能使用 ASP “会话” 对象存储每个客户端的状态。ASP 的 “会话” 对象被锁定在一台机器上,因此不能用于负载平衡的应用程序。

ASP “会话” 对象和 ASP “应用程序” 对象还存在其他限制。使用它们中的任何一个来存储 ADO 记录集都会大大降低可伸缩性,因为它限制了应用程序开发多线程的能力。因此,在这两个对象的任何一个中存储记录集都不是好办法。

分布式通信

Windows DNA 中,选择在不同机器上运行的组件的通信方式是非常容易的:DCOM 是唯一的选择。单纯从体系结构上来看,DCOM 是 COM 的简单扩展。但实际上,DCOM 还有许多其他含义。其中包括:

由于实际上是其自有协议,因而使用 DCOM 与远程 COM+ 对象进行通信非常直接。

只要配置正确,DCOM 将是非常安全的协议。但是要实现这种配置并不容易,因此该协议不太容易使用。尽管如此,DCOM 自身仍能提供很好的分布式身份验证、数据完整性和数据保密性,特别是在 Windows 2000 域内。

由于 DCOM 需要打开任意端口,因此不适合与防火墙配合使用。所以,对于必须通过 Internet 进行通信的应用程序,一般不能使用 DCOM。

访问存储数据

能使用 ADO 构建的数据访问体系结构可以分为两个类别:轻型和重型。轻型 ADO 客户端尽可能简短地保持数据库连接,并使用存储过程写入数据库。轻型客户端使用以下三种方法之一检索数据:

通过使用只读的、仅向前游标填充记录集;

通过存储过程输出参数;

使用数据流(在 ADO 的较新版本中)。

重型客户端则会较长时间地保持数据库连接。这类应用程序依赖于开放式连接以及那些连接所允许的有状态的服务器端游标来执行以下操作:

使记录集能够直接访问其他用户或应用程序所做的更改;

启用保守式锁定;

尽可能减少复制到 ADO 客户端的数据量,以减少网络通信量。与轻型客户端不同,使用服务器端游标的客户端可以将查询结果保留在数据库内,直到真正需要这些数据时再取出。此外,这种方法向记录集复制的元数据较少,而把更多的数据保留在数据库中。

轻型应用程序最具伸缩性,因为它们最有效地使用了数据库连接这一稀有资源。相比之下,重型应用程序必须保持长期有效的数据库连接,因为这是有状态的服务器端游标所要求的。这就大大地限制了应用程序的可伸缩性,尤其不适用于 Internet 服务器应用程序。尽管使用 ADO 开发重型应用程序可能更简单,但通常这并不是最佳选择。

ADO 也不是特别适用于处理 XML 文档等分层数据。ADO 完成此项工作的功能用法复杂,且不易理解。同样地,ADO 对访问 SQL Server 2000 的 XML 功能只提供有限的支持。因此,Windows DNA 应用程序通常避免使用 ADO 来应用分层数据。

将数据传递到客户端

对于所有 N 层应用程序而言,将数据从中间层有效地移动到客户端都是一个关键的环节。当使用 DCOM 与 Windows 客户端通信时,Windows DNA 应用程序可以使用 ADO 断开连接的记录集。当确保浏览器为 Internet Explorer 时,此选项也可用于浏览器客户端。而将数据发送到任意浏览器则比较困难。一种方法是显式地将数据转换为 XML,然后将数据和所有必要的脚本代码发送到浏览器。

返回页首

.NET 环境

.NET 支持传统的 N 层应用程序、Web 服务 应用程序以及将二者的元素结合在一起的应用程序。本节首先介绍 .NET 如何影响 N 层应用程序,然后介绍构建 Web 服务 应用程序过程中的几个主要的体系结构问题。

N 层应用程序与 .NET 绑定在一起

上一节中介绍的某些问题同样适用于 Windows DNA 应用程序和使用 .NET 框架构建的应用程序。例如,只有当满足前面所列的一个或多个条件时,才能使用 COM+(在 .NET 框架中称为企业服务)。同样,将业务逻辑构建为存储过程在很多 N 层应用程序中都可以获得更好的性能。

同时,.NET 框架中到处都是新技术和现有技术的新版本。这些增强功能为 N 层应用程序的优化体系结构带来了多种变化。本节将按照前面介绍的分类,介绍 .NET 框架是如何改变体系结构设计人员在创建 N 层应用程序时所做的决定的。

编写业务逻辑

与在 Windows DNA 中创建 N 层业务逻辑的三种可选方法(ASP 页、COM 组件和存储过程)不同,.NET 框架只提供了两种方法:程序集和存储过程。对于浏览器应用程序,可以使用 Microsoft ASP.NET .aspx 页来创建程序集。与 ASP 不同,在这种情况下完全使用 ASP.NET 编写业务逻辑通常是一个比较好的方法。

其中一个原因就是 ASP.NET 的内含代码选项。在传统的 ASP 页中,以一种可维护的方式混合业务代码和表示代码并不是一件容易的事,而 .aspx 页使用内含代码能够完全将这两种代码分开。其中,Windows DNA 应用程序可能使用 ASP 页和 COM 对象两者来共同进行维护,而使用 .NET 框架构建的应用程序只能使用 ASP.NET。并且,包含在 .aspx 页中的业务逻辑可以采用任何基于 .NET 的语言进行编写,而不仅仅是采用由传统的 ASP 页支持的简单脚本语言。而且,ASP.NET 是编译页面而不是解释页面,因此 ASP.NET 应用程序速度可以非常快。使用 Windows DNA 构建的应用程序可能使用 ASP 页和 COM 对象两者来共同实现足以满足需求的性能,而使用 .NET 提升的性能可能只允许使用 ASP.NET 来构建相同的应用程序。最终,使用 ASP.NET 缓存来减少对常用数据的数据库访问的业务逻辑能显著提高性能。

但是,需要指出的是,对于包含在 .aspx 页中的代码,即使是使用内含代码,其重复使用也比标准的程序集困难。例如,从 Windows 窗体客户端访问 .aspx 页中的代码会遇到很多问题。

构建客户端

使用 .NET 框架可减少对 Windows 客户端的需求,通常只需要一个浏览器客户端即可。其中一个原因在于,ASP.NET Web 控件允许构建和/或购买可重复使用的浏览器图形用户界面 (GUI) 元素,从而能够更方便地构建更有用的浏览器客户端。而且可以将基于 .NET 框架的组件下载到 Internet Explorer 客户端,然后使用部分信任来运行这些组件(而不使用 ActiveX 控件所要求的全是全非信任模式),这有助于构建更好的用户界面。

管理浏览器应用程序中的状态

由于 ASP “会话” 对象被绑定到一台机器上,因此它并未发挥出应有的作用,而使用 .NET 框架就避免了这种限制。与 ASP 不同,ASP.NET “会话” 对象可以被两台或多台机器共享。从而可以使用 “会话” 对象来维护负载平衡的 Web 服务器领域中的状态,使其更加有用。而且,由于 “会话” 对象的内容可以选择存储在 SQL Server 数据库中,这种机制可用于出现故障时必须一直保持每个客户端的状态的应用程序中。

影响 ASP.NET 应用程序体系结构的另一个重要更改在于,数据集可以存储在 “会话” 和 “应用程序” 对象中而无需包含线程,这一点与 ASP 不同。也就是说,在 Windows DNA 中严格规定的不能将记录集存储在这些对象中的规则不适用于 .NET 框架中的数据集。这就使得查询结果的存储更加简单也更加自然。

分布式通信

Windows DNA 相比,.NET 框架为应用程序的分布式部件之间的通信提供了更多选择,包括:

.NET Remoting,提供 TCP 通道和 HTTP 通道;

ASP.NET 支持在 .asmx 页中实现的、可通过 SOAP 调用的 XML Web 服务;

与远程 COM 对象通信所需的 DCOM。

选项越多,意味着体系结构的选择也越多,这也意味着做选择时有更多需要考虑的因素。使用 .NET 框架创建分布式应用程序时要了解的体系结构问题包括:

直接与远程 COM+ 对象进行通信要求使用 DCOM,而不能使用 .NET Remoting。由于 DCOM 的建立和使用都相当复杂,因此应尽量避免这种通信。在某些情况下,有必要通过托管代码处理现有的 COM+ 对象,尽管这样做所要求的 COM 互操作性会降低性能。

.NET Remoting TCP 通道没有提供内置的安全性。与 DCOM 不同,它不提供严格的身份验证、数据完整性或数据保密服务。但它并非一无是处,TCP 通道比 DCOM 更容易配置。

DCOM 不能很好地与防火墙配合使用,.NET Remoting HTTP 通道与之不同,它是专门为在 Internet 上进行有效通信而设计的。而且,由于可以使用 SSL,此选项能够为数据提供安全的路径。通常,对于 Intranet 通信而言,TCP 通道是较好的选择;而对于 Internet 通信,则更适合使用 HTTP 通道或 ASP.NET SOAP 支持。

.NET Remoting HTTP 通道和用于 XML Web 服务 的 ASP.NET 支持都能实现 SOAP。然而,这两种实现方式是截然不同的,每种方式都具有其特定的目的。.NET Remoting 注重保留公用语言运行时的确切语义,因此,当远程系统同样运行 .NET 框架时,它是最佳选择。ASP.NET 则注重提供绝对标准的 XML Web 服务,因此当远程系统是基于 .NET 的平台或任何其他平台时,它是最佳选择。而且 ASP.NET 比 .NET Remoting HTTP 通道的速度快。但 HTTP 通道也有优点,它允许通过引用和真正的异步回调来传递参数,这是 ASP.NET 中的 SOAP 支持所不具备的功能。

访问存储数据

ADO 能够方便地构建重型客户端,但客户端的伸缩性较差,ADO.NET 与 ADO 不同,它更适用于构建轻型客户端。ADO.NET 客户端使用仅向前的只读游标读取数据。它不支持有状态的服务器端游标,因此其编程模式鼓励短时间的连接。直接读取和处理数据的客户端可以使用 ADO.NET 的 DataReader 对象,它不为返回的数据提供缓存。或者,可以将数据读入 “数据集” 对象中,将其作为从 SQL 查询和其他源中返回的数据的缓存。但是,与 ADO 记录集不同,数据集不能显式地维护与数据库的开放连接。

如前面所述,ADO 生成的重型方法还存在一些其他问题。这些问题可以在 ADO.NET 中解决,如下所示:

对于将数据存储在数据集并要求访问由其他用户或应用程序所做的更改的 ADO.NET 客户端,需要包含显式代码才能进行这些更改。该代码通常还需要为每个所进行的检查打开一个数据库连接。

尽管 ADO.NET 并不直接支持保守式锁定,但通过使用 ADO.NET 事务或在存储过程中实现所需的功能,客户端仍然可以获得同样的效果。

ADO 不同,ADO.NET 不允许将部分查询结果保留在数据库中(可以使用服务器端游标从中进行访问)。虽然 ADO.NET 确实比 ADO 检索的元数据要少,但应用程序仍应设计为能够将所有的查询结果从数据库传递到 ADO.NET 客户端。

ADO.NET 中影响体系结构选择的另一项更改是其对处理分层数据(特别是 XML 文档)的支持增强了。将 ADO.NET DataSet 转换为 XML 是非常直接的,因为只需访问 SQL Server 2000 的 XML 功能即可。因此,在 Windows DNA 环境中可能已经与关系模型强制配合的分层数据现在能够以其原始形式进行访问。有关详细信息,请参见相关读物一节。

将数据传递到客户端

将数据有效地传递到客户端对于在 .NET 框架上构建的 N 层应用程序和使用 Windows DNA 构建的应用程序同样重要。一项重要的更改在于,ADO.NET 数据集可自动序列化成 XML,从而使得各层之间的数据传递更加简单。虽然在 Windows DNA 中也可以使用这种方法,但 .NET 使通过 XML 的信息交换变得更加简单、直接。

XML Web 服务 体系结构

在构建分布式应用程序的过程中,可以通过多种方法来使用 XML Web 服务 的 SOAP、Web 服务说明语言 (WSDL) 以及其他技术。例如:

使用 SOAP 而不是仅仅使用 HTTP 连接到 N 层应用程序的 Web 客户端。连接建立后,该客户端可以是能够进行 SOAP 调用的任意设备。之后,客户端可以为其用户提供更多的功能,因为它能够直接调用远程服务器中的方法。

将可能是在基于 .NET 框架的平台上构建的 N 层应用程序与在其他平台(例如 Java 应用程序服务器)上构建的另一个应用程序连接起来。

连接两个大型应用程序,或者连接一个企业资源规划 (ERP) 系统与另一个 ERP 系统或任何其他应用程序。正如这些示例所示,XML Web 服务 不仅仅适用于 N 层应用程序,其应用范围十分广阔。

不管如何使用,XML Web 服务 都会带来许多新的体系结构问题。XML Web 服务 与 N 层应用程序通常使用的更为传统的中间件技术之间的最主要的差别或许在于,XML Web 服务 提供的是松散耦合。遗憾的是,这个词对于不同的用户有着不同的含义。在本文中,它是指具有以下特点的通信应用程序:

应用程序在很大程度上相互独立,并且通常由不同的组织控制。

并不完全可靠。不能保证每个通信应用程序在所有时间都可用。

其交互操作可以是同步的,也可以是异步的。Web 服务 客户端可能阻塞对某个请求的响应的等待,也可以在发出请求后去做其他事,稍后再来检查响应。

这些基本特点为使用 XML Web 服务 的应用程序提供了很多体系结构方面的原则。虽然有些问题可能会在以后的工作中得到解决,如 Microsoft 的 Global XML Web 服务 Architecture (GXA) specifications 中所述,但是目前,创建有效的 XML Web 服务 应用程序的用户必须要了解这些问题。其中包括:

安全性可能会比较复杂。预先规划端对端身份验证和有效授权十分重要。端对端的数据完整性和数据保密性对某些应用程序也很重要。可能有必要在不同的安全机制之间进行映射,当然最好尽量避免这种情况。有关详细信息,请参见相关读物一节。

互操作性可能会成为问题。由于规范还相对不成熟,不同供应商的 SOAP 实现还不能始终很好地协作。有关详细信息,请参阅相关读物一节。

修改现有应用程序以便可以通过 XML Web 服务 进行访问时,可能会出现问题。当把从未打算要在一起使用的程序连接在一起时,总会出现速度、可伸缩性和安全性等问题。现有应用程序通常不是作为服务器而构建的,因此处理一些很小的请求就会轻易搞垮它们。减少请求数量,而增加每个请求中包含的数据可能会提高应用程序的性能。此外,现有应用程序通常不能处理预料之外的负载,例如向 Internet 公开软件时可能产生的负载。如果可能,使用某种排队机制以在请求被响应之前将请求存储起来,这可能会有所帮助。

调节故障非常重要。尤其是只需要一次语义的请求,通常需要格外小心。例如,请求可能会超时,从而触发重试,但原来的请求可能只是因为某种原因被延迟而已。如果针对单个调用执行两次远程 Web service 会出现问题,则必须创建某种机制来解决这个问题。

不可能提供依赖于分布式锁定(跨越组织边界保持)的端对端事务。大多数组织不允许“外来”应用程序锁定数据,因此不可能实现两阶段提交样式的事务。而只能考虑为任何必要的回滚使用补偿事务。

由于收到的数据可能跨越应用程序和组织边界,Web 服务 通信的每一端可能都需要仔细检查该数据。虽然应用程序的创建者可能十分信任由他们自己的应用程序的其他部分所生成的数据的准确性,但他们不能对其他应用程序抱以同样的信任。收到的信息甚至可能包含恶意代码,因此必须仔细检查。

SOAP 及其携带的 XML 定义的数据非常多。在一个调用中传递太多数据可能会搞垮低带宽的网络。反过来,在一个调用中传递的数据太少又会搞垮处理这些请求的应用程序。尽管这很困难,但找到正确的平衡点还是很重要的。有关详细信息,请参阅相关读物一节。

返回页首

小结

体系结构是关键。为应用程序(尤其是分布于多个系统的应用程序)选择正确的体系结构是至关重要的。如果选择了错误的体系结构,不管开发人员多么优秀,通常都无法在实现过程中修复。错误的决定会导致性能降低、安全性降低以及应用程序需要更新时可用的选项较少。

Windows DNA 为 N 层应用程序奠定了一个坚实的基础,Windows 开发人员可以根据他们从 DNA 领域所学到的知识来构建应用程序,把其中的大部分应用到新的 .NET 环境中。不过,了解本文所建议的更改将有助于创建更快、更安全、功能更强的应用程序。对于 N 层应用程序以及采用 Web 服务 新技术的应用程序来说,.NET 可提供的功能很多。

返回页首

相关读物

Windows DNA 环境

Architecture Decisions for Dynamic Web Applications:Performance, Scalability, and Reliability

Duwamish Online Application Architecture

.NET 环境

Performance Comparison:Transaction Control

Performance Comparison:Data Access Techniques

.NET Architectural Sample Applications

XML Web 服务 体系结构中的问题

Real SOAP Security

Designing Your Web Service for Maximum Interoperability

DIME:Sending Binary Data with Your SOAP Messages

转到原英文页面


 

 

 

  漫谈.Net PetShop和Duwamish ADO.NET数据库编程

 

 

 

 

  概述

 

  ADO.Net为我们提供了强大的数据库开发能力,它内置的多个对象为我们的数据库编程提供了不同的选择。但是在允许我们灵活选用的同时,许多初学者也很迷惑,我到底是应该使用DataReader还是应该使用DataAdapter?我只想读取一小部分数据,难道我一定要Fill满整个DataSet吗?为什么DataReader不能和RecordSet一样提供一个数据更新的方法?DataSet到底有什么好处?

 

  在本文中,我将对.Net PetShop的数据库编程模式和Duwamish的数据库编程模式进行一些简单的分析和对比。如果您也有以上疑问的话,相信在读完本文之后,就可以根据具体的需要来制定一个最适合您应用的数据库编程模式。

 

  .Net PetShop和Duwamish简单介绍

 

  相信大家一定听说过有名的"宠物店大战",没错,本文的主角之一就是获胜方.Net PetShop,微软号称以27倍的速度和1/4的代码量遥遥领先于基于J2EE的PetStore宠物商店。虽然SUN也曾对此抱怨过不满,指责此"大战"有水分,不过无论如何,.Net PetShop绝对是一个经典的.Net实例教程,至少为我们提供了一条赶超J2EE的“捷径=" :),它的下载地址是:http://www.gotdotnet.com/team/compare

 

 

.Net PetShop宠物网上商店首页

 

   而Duwamish则是一个外表简单,内部却极其复杂的一个网上书店的.Net完整应用范例,作为一个微软官方的Sample,它同时提供了C#和VB.Net两种语言版本,并且还附上了大量详尽的中文资料,如果打印出来,实在是居家旅行,临睡入厕必备之物。什么?您没听说过?呵呵,如果您装了Visual Studio .Net的话,它就在您的硬盘上静静的躺着呢,不过还没有被安装,您可以在您的vs.net 的Enterprise Samples目录下找到并安装它,例如:C:/Program Files/Microsoft Visual Studio .NET/Enterprise Samples/Duwamish 7.0 CS。

 

 

 

Duwamish网上电子书店首页

 

  结构简述

 

  两家商店都采用了n层应用结构(毫无疑问,n层结构的应用架构应该绝对是您开发.Net应用的首选,哪怕您只想做一个网页计数器),不同的是,PetShop采用的是最常见的三层应用结构,分别为表示层,中间层和数据层。而Duwamish则采用的是一个四层应用结构,并使用不同的项目分隔开,分别为表示层,业务外观层,业务规则层和数据层。至于这两种结构分别有什么优点和缺点,以及为什么要这么分层,我们不进行详细讨论,因为本文的重点不在于此。我们主要分析的是他们的数据库编程的模式。

 

 

   漫谈.Net PetShop和Duwamish ADO.NET数据库编程

 

2002-10-18· ·卢彦··Asp.Net中文专业网

 

 

上一页  1 2 3  下一页

 

  Duwamish数据访问剖析

 

  首先,我们来看看Duwamish书店,它采用的是DataAdapter和DataSet配合的数据存储模式,所不同的是,它对DataSet进行子类化扩展作为数据载体,也就是采用定制的DataSet来进行层间的数据传输,下面是一个定制的DataSet示例:

 

 

public class BookData : DataSet

     {

public BookData()

         {

             //

             // Create the tables in the dataset

             //

             BuildDataTables();

         }

       private void BuildDataTables()

         {

            //

            // Create the Books table

            //

            DataTable table   = new DataTable(BOOKS_TABLE);

            DataColumnCollection columns = table.Columns;

           

   columns.Add(PKID_FIELD, typeof(System.Int32));

            columns.Add(TYPE_ID_FIELD, typeof(System.Int32));

            columns.Add(PUBLISHER_ID_FIELD, typeof(System.Int32));

            columns.Add(PUBLICATION_YEAR_FIELD, typeof(System.Int16));

            columns.Add(ISBN_FIELD, typeof(System.String));

            columns.Add(IMAGE_FILE_SPEC_FIELD, typeof(System.String));

            columns.Add(TITLE_FIELD, typeof(System.String));

            columns.Add(DESCRIPTION_FIELD, typeof(System.String));

            columns.Add(UNIT_PRICE_FIELD, typeof(System.Decimal));

            columns.Add(UNIT_COST_FIELD, typeof(System.Decimal));

            columns.Add(ITEM_TYPE_FIELD, typeof(System.String));

            columns.Add(PUBLISHER_NAME_FIELD, typeof(System.String));

 

    this.Tables.Add(table);

         }

………

}

 

  我们可以看到它有一个BuildDataTables方法,并且在构造函数中调用,这样,定制的Books表就和这个DataSet捆绑在一起了,省得以后还要进行Column Mapping,这真是个好主意,我怎么就没有想到呢? :)

 

  解决了数据结构,接下来看看数据层的代码实现,在Duwamish中,数据层中有5个类,分别是Books,Categories,Customers和Orders,每个类分别只负责有关数据的存取。下面是其中一个类的示例代码:

 

 

private SqlDataAdapter dsCommand;

public BookData GetBookById(int bookId)

{

     return FillBookData("GetBookById", "@BookId", bookId.ToString());

}

private BookData FillBookData(String commandText, String paramName, String paramValue)

{

    if (dsCommand == null )

    {

        throw new System.ObjectDisposedException( GetType().FullName );

    }           

    BookData   data    = new BookData();

    SqlCommand command = dsCommand.SelectCommand;

 

    command.CommandText = commandText;

    command.CommandType = CommandType.StoredProcedure; // use stored proc for perf

    SqlParameter param = new SqlParameter(paramName, SqlDbType.NVarChar, 255);

    param.Value = paramValue;

    command.Parameters.Add(param);           

 

    dsCommand.Fill(data);

    return data;

}

 

  这里就是数据层的代码了,我们在这里可以看到Duwamish采用了DataAdapter来将数据填充到定制的DataSet中,然后返回该DataSet。我感到很奇怪的是在数据存取层中竟然可以看到GetBookById这样具体的数据存取方法,虽然最后还是有一个抽象出来的FillBookData方法,但是上面还有三层啊,底层都做到这份上了,那上层都做些什么呢?答案是数据检查,上层基本上都在做一些很严密的数据合法性校验(当然也会包括一些比较复杂的事务逻辑,但是并不多),示例代码如下:

 

 

public CustomerData GetCustomerByEmail(String emailAddress, String password)

        {

            //

            // Check preconditions

            //

            ApplicationAssert.CheckCondition(emailAddress != String.Empty, "Email address is required",

ApplicationAssert.LineNumber);

            ApplicationAssert.CheckCondition(password != String.Empty, "Password is required",

ApplicationAssert.LineNumber);

            //

            // Get the customer dataSet

            //

            CustomerData dataSet;

            using (DataAccess.Customers customersDataAccess = new DataAccess.Customers())

            {

                dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);

            }

            //   

            // Verify the customer's password

            //

         DataRowCollection rows = dataSet.Tables[CustomerData.CUSTOMERS_TABLE].Rows;

        

            if ( ( rows.Count == 1 ) && rows[0][CustomerData.PASSWORD_FIELD].Equals(password) )

         {

                return dataSet;

         }

            else

            {       

             return null;

            }

        } 

 

  在这个方法中,真正进行数据存取的实际上只有

 

  dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);

 

  这么一句,是直接调用的数据层。其它都是在进行合法性校验,我们可以感悟到,进行一个真正的企业级开发需要考虑的系统健壮性有多么重要。

 

 

 

 

阅读全文
0 0

相关文章推荐

img
取 消
img