使用 C#Builder Architect 为 DB2 UDB 创建模型驱动的 Windows 应用程序

使用 C#Builder Architect 为 DB2 UDB 创建模型驱动的 Windows 应用程序

Jeremy McGee (jeremy@mcgee.demon.co.uk)
独立顾问
2004 年 2 月
摘錄自 IBM公司網站 > DB2開發者園地 > 本文


简介

Borland C#BuilderTM Architect 扩展了 C#Builder 的开发能力,使之能进行模型驱动的开发。通过自动实施部分 UML 软件模型,节省了业务逻辑编码的时间。

本文中,我将简述如何创建一个简单的模型驱动的应用程序,该应用程序使用 DB2 作为存储器。我假设您已经熟悉了 C#Builder 的基本用法,如果还没有的话,请参阅 developerWorks DB2 和 Borland 专区 中的其他一些文章。

可从 Borland Web site 获得 C#Builder Architect 的试用版,以及第一版用以解决某些编译问题的补丁。

UML 模型

统一建模语言(Unified Modeling Language,UML)可用于表示系统中的对象、对象之间的相互关系以及它们所执行的过程。UML 本身就非常全面,有各种不同类型的图,这些图组合在一起可用于表示应用程序的各个方面。

C#Builder Architect 使用两种 UML 图:类图和包图。这是两种基本的用于表示类的图。

C#Builder Architect 如何节省开发时间

C#Builder Architect 包括了一种新形式的 C# 项目:Borland ECO 应用程序。ECO(Enterprise Core Object)是指企业核心对象构架,它创建并存储来自于 UML 类图和包图的 .NET Framework 类。例如,一个简单的 HR 应用程序模型可能看起来类似于:

图 1. 简单 HR 应用程序的 UML 类图

这个应用程序要求保留部门、雇员和应聘者的简单日志记录。

UML 类图设计为一种可直接阅读的形式。在本例中,您有一个超类 Person 以及继承了该超类的特性(属性)和方法(操作)的两个子类:Employee 和 Candidate。Department 类有一个或者多个与之关联的 employee 或 candidate。

“传统的”应用程序必须要维护存储这些数据项的表并实施完整性约束。这就意味着要编写和维护大量的程序代码。

而这里,如果您希望提取工作职位作为一个类,并且进一步定义雇员、应聘者和工作之间的关联。在传统的 C# 应用程序中,您需要重写应用程序中的大量内容来完成。而在诸如 ECO 这种模型驱动的应用程序系统中,很容易地只需修改模型并重新生成应用程序就可以做到。数据甚至可以识别这种改变而做出相应的迁移。

利用 C#Builder Architect 设计一个“UML 包”来包含这些核心类。而“EcoSpace”接着使用该 UML 包来定义和在内存中存储这些类实例化后的对象。EcoSpace 能包含将对象写入 DB2 数据库的“持久性处理程序”。

最终结果是不需要定义数据表以及编写代码来进行维护。ECO 取而代之的是,使用面向对象的方法在 DB2 数据库中透明地存储这些对象。

本文中,我将使用 ECO 快速地设计一个完整的应用程序,用以维护以上所列的四个表。虽然最终结果看上去不会特别优秀,但显示了 ECO 所带来的一种功能强大的方法,用以维护相当复杂的对象及其相互关系。

ECO 应用程序

ECO 应用程序是一种特殊形式的 C# 程序,它包含了额外的容器和使用 ECO 的类。它只能在 Borland C#Builder Architect 中被加载和编辑。

要创建应用程序,先选择 File | New | Other…,然后选择 C# Projects,并从列表中选取 ECO Application。选择一个项目名(例如 HRApp)后单击 OK

该应用程序看起来类似于其他任何使用 C#Builder 创建的空项目一样。然而,如果仔细观察,将发现在默认的 WinForm 上添加了一个额外的组件。稍后当谈到如何连接窗体上的组件和数据库中的对象时,我将介绍如何引用句柄 rhRoot。

如果查看 Project Manager,您将发现包括了三个附加的源代码单元:

CoreClasses.cs 包含了应用程序使用的 UML 包的类的定义。本代码单元由 C#Builder Architect 自动管理并广泛使用了 C# 的属性。您不必直接编辑该文件。

EcoSpace.cs 是将 CoreClasses.cs 中定义的类转变为对象的地方。EcoSpace 还包含了将对象存储到 DB2 数据库中的持久性映射程序。一个应用程序可以包含几个 EcoSpace,还可使用 UML 包将多个类分别放到这几个 EcoSpaces 中。EcoSpace 中的类将存储到与之关联的 DB2 数据库中。

EcoWinForm.cs 是一个专门负责直接使用 EcoSpace 上的对象的 WinForm。稍后您将看到,它是以一种特殊方式进行实例化的。

使用 Model View

要创建模型,先切换到 Model View 并展开最上面的叶子。您将会看到在下一层中有三个叶子:

图 2. 空 ECO 应用程序的初始模型视图

名为 CoreClassesPackage 的灰色“文件夹”图标表示应用程序的逻辑(或者域)模型。就是在这里用 UML 定义来创建类。Model View 从 CoreClasses.cs 读取这些内容。

以您的项目命名的白色“应用程序”图标表示模型的实现,这里进行特定语言和特定操作的定义。应用程序中的每一个 C# 类在该图标下都一个对应的叶子,包括通过 UML 图定义的类以及由 C#Builder 自动定义的应用程序的另一部分类。请注意,为了实现模型,C#Builder 将会为 ECO 类的定义自动添加额外的内部成员。

第三个图标是一个彩色的“模型”图标。它用于打开主 IDE 中的 UML 图。双击该图标后,对于空应用程序,您将在顶层看到 UML 图中的两个包:CoreClassesPackage 和 implementation。

图 3: 空应用程序的初始总体 UML 图

双击图中的 CoreClassesPackage 后,往下一层是应用程序的 UML 设计器。因为还未定义任何对象,所以该设计器还是一片空白。

定义 UML 模型中的类

在 UML 设计器中,画出模型的图形化表示。看起来就像这样:

图 4:UML 模型的最终版本

要创建 Person 类,单击工具面板上的 Class 图标,并在设计界面中画一个方框。这样就添加了一个名为 Class_1 的空类,稍等片刻后就可以输入类名 Person 了。

接下来是添加特性,在 UML 中也称作属性。右击 Person 类并选择 Add | Attribute 。输入 Name: string 以命名属性,并将其定义为内建的 String 类。单击 Enter,C#Builder 将自动添加可见的运算符“+”。

对其他的属性重复执行相同步骤,这里我建议 HomePhone:stringHomeEmail:string。ECO 最大的优点之一就是可以容易地添加新的属性,而不必重新编写整个应用程序,甚至连数据存储都能被自动更新。

Person 类完成后,用同样的方法添加 Employee 类和 Candidate 类。您将很快为其添加属性。

这两个都是 Person 类的子类。在英语中,employee 和 candidate 也都是指人。C#Builder 中可通过工具面板上的箭头工具显示这种“泛化”关系。用该工具从 Employee 类向 Person 类画一条直线就可以表示这种关系。对于 Candidate 类也是如此。

现在,您可以为这两个新的子类添加额外属性了。Employee 类应再添加三个属性: WorkPhone:stringWorkEmail:stringJobTitle: string。Candidate 类只有一个额外属性:JobSought:string。因为 Employee 和 Candidate 是 Person 的子类,所以这些属性还会加上您在 Person 类中已经定义了的那些属性。

接下来,您将添加第四个类: Department。它将用于为特定的 department 筛选 employee 和 candidate。添加属性: Name:stringLocation:string。您稍后还可以随时添加更多属性。

定义类之间的关联

下一步就是定义 employee、candidate 及其 department 之间的 UML 关联。单击工具面板上的 Association 图标,并从 Candidate 类向 Department 类画一条直线。C#Builder 将自动创建名为 Association_1 的关联,并给每一端指定一个默认的 重数

这里所做的是在这两个类的对象之间定义简单的一对一关系。重数“0..1”表明对于某个特定的 candidate,将会有零个或一个与之匹配的 department。同样地,每个 department 可能有零个或一个相关联的 candidate。

这并不是您希望的情况。实际中,department 可能有零个或多个 candidate,也就是说重数应该为“0..*”。为了简化事情,假设每个 candidate 申请工作的 department 有且只有一个。换句话说,就是重数为“1”。

为了进行调整,单击 association,并使用 Object Inspector 来设置以下属性。您需要依照以下方法扩展 End1 和 End2 属性:


End1.Multiplicity: 0..*
End1.Name: mightEmploy

End2.Multiplcity: 1
End2.Name: mightWorkFor

最终结果应该如上面的图 4 所示。

关联端的名字是很重要的,因为在它们自己的权限内,名字就作为属性来使用。

对于 employee 及其 department 之间的关联也重复执行最后这两个步骤。设置关联属性为:


End1.Multiplicity: 0..*
End1.Name: employs

End2.Multiplicity: 1
End2.Name: worksFor

已经很到位了,这些就是您创建类需要做的全部工作。接着,ECO 将维护这些关系,并确保创建的任何对象都遵循这些关系。因此,例如,一个 Employee 对象“myEmployee”将会有一个属性“myEmployee.worksFor”,该属性就是指它们的 Department 对象。同样地,一个 Department 对象“selDepartment”也会有一个属性“selDepartment.mightEmploy”,而它指的则是 Candidate 对象的集合。

但是我们已经提前做了一些工作。现在先要创建用户界面,这样才能实例化这些对象。

组织用户界面

在创建用户界面之前, 编译此应用程序 是很重要的。若要查看 CoreClasses.cs 源代码(切换到 Project Manager 并双击文件),您将发现 UML 编辑器已经在类旁边创建了属性(方括号中)。ECO 将在内部通过它们来读取模型并正确地生成对象。

C# 中,属性通过 .NET 反射起作用,这是指类可以进行自我描述的能力。而直到应用程序被编译后,这些类才存在。因此,直到您按 Ctrl-F9 来生成应用程序后,.NET 反射才有效。(注意,对于这一点,C#Builder Architect 的早期版本将会返回一个错误。您可以从 Borland Web site 下载并安装最新更新来解决这个问题。)

使用 C#Builder 时,有相当多的地方都需要通过编译来使得反射工作。因此,就像记住保存项目一样,最好是养成这种习惯:每当调整了模型后,就按 Ctrl-F9 进行编译。

为该应用程序创建的用户界面看上去也没有什么特别,但它将展示如何使用已创建的类。现在要向应用程序的主 WinForm 添加三个 DataGrid 组件。这样,我们就可以输入 department 和 employee,并可查看系统中全部人员的列表了。接着,您将添加一个额外的窗体用于添加和删除 candidate。

切换到 Project Manager 并双击 WinForm.cs 源文件。您起先看到的窗体设计器将显示为一个空窗体。

对于 ECO Application来说,WinForm的工作方式非常类似于常规的 Windows Form 应用程序。这就是第一次加载应用程序时所显示的窗体。

然而,如您所注意到的,在上面还放置了一个额外的组件:rhRoot,这是一个 ReferenceHandle。在ECO 中,引用句柄用于指向应用程序的模型中的一个对象。单击 rhRoot 并设置 EcoSpaceType 属性来指向整个 EcoSpace:

图 5:ECO 应用程序中的每个 WinForm 都有一个引用句柄 rhRoot

如果在下拉列表中看不到 EcoSpaceType 的值,那么很可能是您还没有编译应用程序。请按 Ctrl-F9 并再试一次。

ECO 真正强大之处在于,它能很容易地使用由它定义的对象。其关键就是 ExpressionHandle,ExpressionHandle 使得模型中的对象可以像正规的、普通的、常规的 .NET 数据集那样使用。它们可以从那里连接到任何数据相关的组件,就好像从 ADO.NET 获取数据一般。所有熟悉的关于使用数据集的编程技术也同样可用于 ECO ExpressionHandle。

在窗体上放置一个 ExpressionHandle,并按以下方法设置其属性:


Name: ehDepartment
RootHandle: rhRoot

单击紧挨着 Expression 的属性编辑器。在这里,可以使用 UML 对象约束语言(Object Constraint Language,OCL)以图形化方式为该句柄构建一个表达式。

图 6:ECO 包括一个 OCL expression editor

还需要 Department 对象,因此双击在右手边窗格上的 Department。返回一个 .NET 集合的方法是 .allinstances,因此要双击它。在 OCL expression editor 底部的 OCL 解析器能确认语法是否正确以及是否返回了一个集合。

目前要做的就是向窗体添加一个 DataGrid 并将其 DataSource 属性指向 ehDepartment。设置完后,将会看到用于 Name 和 Location 的列已被自动添加。

接下来,需要采用一个方法来创建对象。添加一个按钮并设置:


Name: btnAddDepartment
Text: Add Dept

与 Click 事件处理程序不同,添加一行代码:

new Department(EcoSpace);

运行该应用程序。单击 Add Dept 按钮,您将在网格中看到一个空的 Department 对象。输入一些数据,并再次单击按钮来输入另一个 Department。

图 7:简单的用户界面

存储数据

现在,您已经完成了创建并编辑 Department 对象所需的全部工作。然而,一旦关闭应用程序,所做的任何修改都会随之消失。这是因为对象都是在内存中创建的,而且也没有在某一点存入磁盘。

正如已经讨论过的,EcoSpace 是应用程序中定义和存储对象的中心部分。C#Builder Architect 提供了一个 EcoSpace 设计器,它可以包含 持久性映射程序 ,用于将对象存储到关系数据库中。IBM DB2 就是一个用做持久性存储的好选择。

需要记住的是,ECO 真正需要有自己的数据库来存储对象。这是因为要用几个内部系统表与包含数据的表一起来控制对象。如果通过 IBM DB2 管理工具来浏览数据,您将看到在这些表中也有一些附加字段,它们也是在内部使用的。

在服务器上通过 DB2 命令提示符,或者通过 Control Center,创建一个名为 ECOHR 的新数据库。以常规方式设置客户机工作站指向该数据库,并将数据库添加到 C#Builder Data Explorer 的可用数据库中。(请参阅 这篇文章 获取更多信息。)

EcoSpace.cs 源文件有自己的图形编辑器,可用于设置从对象到数据库的持久性映射。首先,通过 Project Manager 切换到 EcoSpace.cs 设计器。然后在工作区放入一个 BdpConnection 组件,并通过 Object Inspector 底部的 Connection Editor 将其指向数据库。这用于将数据存入 DB2 数据库,与使用 Borland Data Provider 的常规应用程序一样。(要获得 Borland Data Provider 的更多信息,请单击 此处。)

然后,选择持久性映射程序组件。您将使用组件 persistenceMapperBdp 映射到 Borland Data Provider。C#Builder Architect 中还有另外两个组件:persistenceMapperSql 和 persistenceMapperXml。persistenceMapperSql 可通过 ADO.NET SqlConnection 组件直接连接 SQL Server,而 persistenceMapperXml 则是用 XML 文件存储数据。

选择 persistenceMapperBdp 组件,并将之放到 EcoSpace 设计器。将其 Connection 属性设置为先前创建的 bdpConnection1

下一步就是设置持久性映射程序将要使用的特殊 SQL 语言,本例中使用 DB2 SQL。用属性编辑器一步就可以完成。但还是看看具体如何做:首先展开 Object Inspector 中的 SqlDatabaseConfig 属性,然后单击 DB2 Setup 属性编辑器。请注意查看对 SqlDatabaseConfig 属性所做的修改。

图 8:为 DB2 定制持久性映射程序

您可以根据应用程序的需要调整这些参数。其中一些参数会对性能带来相当大的影响。例如,在 FetchBlockSize 中设置的单个 SELECT 语句检索 250 行的限制就是如此。

最后,还需要将 EcoSpace 的 PersistenceMapper 属性设置为指向您刚刚创建的持久性映射程序。单击其背景并设置属性为 persistenceMapperBdp1 组件。

初始化数据库

EcoSpace 设计器的右下方有一个很小的工具栏,负责维护底层的数据库。

图 9:EcoSpace 中用于创建与维护到 DB2 数据库的映射的工具栏

单击最左边的图标。将出现一个对话框,要求您确认最近是否编译了应用程序。这是很重要的一步。因为如果没有这样做,数据库可能是由过时的模型定义生成的。

在 IDE 的底部将显示 Messages 窗口。生成数据库后将会显示一条消息,否则显示一个诊断错误。

图 10:ECO 在消息窗格上有自己的输出窗口

加载并保存数据库中的对象

本文的最后阶段就是将对象存入数据库。这需要单个方法调用。

为了保持跟踪事情的发展,你要在窗体中添加一个按钮来保存 EcoSpace 对象。回到 WinForm.cs 并在底部添加一个按钮,将其 Name 属性设为 btnSaveText 属性设置为 Save

还应添加 btnSave 按钮的 Click 处理程序:

EcoSpace.UpdateDatabase()

这就是需要做的全部工作,现在单击按钮时,ECO 会自动地将对象存入数据库。

图 11:应用程序正在将对象存入数据库

运行应用程序并输入几行数据,然后单击 Save 按钮。关闭应用程序后重新运行一次。加载应用程序时,您将发现 ECO 已经自动地存储了对象。

您还可以控制对象的恢复。如果滚动屏幕到达 WinForm 的构造函数,您将发现加载应用程序时,C#Builder 已经自动为 EcoSpace 的初始化添加了代码。如果有必要,在 EcoSpace 加载之前,您也可以在此处添加自己的代码来设置数据库连接,也许可用于授权用户或登录数据库。

结束语以及下一步工作

因为 ECO 在内部处理所有的数据存储,所以对于不是特别需要使用现有数据表的新开发项目来说,ECO 应用程序是很完美的。尤其对于习惯使用 UML 模型来构建应用程序框架的开发小组来说更是如此。然而,对于数据库模式的应用程序来说,可能会觉得 ECO 不是一种有效的创建应用程序的方法。

ECO 可以使用任何关系数据库来存储对象,但特别适合使用 IBM DB2 UDB。该数据库的可伸缩性和可靠性,加上它能运行在范围很广的硬件上,使之成为了 ECO 的完美补充。

下一步工作
虽然本文已经创建了一个相当复杂的模型,但用户还只能维护一类对象。下一篇文章中,我将扩展用户界面以便控制更多的类,并检验它们在代码中如何被操纵。

参考资料

  • 使用 ECO 之前,您需要理解 C#Builder 的基本规则及其如何使用数据库。developerWorks 的 这篇文章 很好地介绍了有关内容。

  • 您还可以在 此处 找到如何区分 ADO.NET 体系结构和其他 Borland 产品的更多信息。

  • 要得到 ECO 的更多信息,请参阅 Borland Web site

  • 要得到 ECO 中所使用的 UML 建模语言的更多信息,请参阅 www.omg.org/umlwww.rational.com/uml

到首页

关于作者

Jeremy McGee 最初在 Commodore PET 上用 BASIC 编写应用程序。对于在早期的苹果机上用冰箱般大小的激光打印机编排书那么长的出版物,他至今记忆犹新。从那时起,他担任过 DEC VAX 的系统管理员、Borland Paradox 的技术支持工程师,以及启动欧洲 Borland Delphi 的小组成员之一。目前,Jeremy 在英国的南安普敦经营一家顾问公司。

以下术语是 IBM 公司在美国和/或其他国家或地区的商标:IBM、AS/400、DB2、DB2 通用数据库、Information Integrator、iSeries、OS/390 和 z/OS。

Microsoft 是 Microsoft 公司的注册商标。

UNIX 是 The Open Group 在美国和其他国家或地区的注册商标。

其他公司、产品或服务名称可能是其他公司的商标或服务标记。

IBM 版权和商标信息

posted on 2004-10-29 16:16  Jason Cheng  阅读(311)  评论(0编辑  收藏  举报