《关于VisiBroker For Delphi的使用》 数据挖掘交友
-CORBA技术实践(一) 数据挖掘实验室
宜昌市中心人民医院 赵普昉
email: 3boy@sohu.com
数据挖掘研究院
4、实例设计与分析 数据挖掘研究院
上一次我想大家介绍了一个在CORBA中使用Pooler的小程序,这段代码中使用了较为高级的编写方法,在分析这个实例之前,我想和大家谈一点设计工具的应用,当然我会在本文的后续文章中深入探讨关于这些辅助手段的应用,在这里我只想简要的描述一下,为正真的工程项目中实现CORBA技术做好相应的知识储备。 数据挖掘交友
前面我介绍了接口描述语言(IDL)的一些较为基础语言要素,如果只是在Delphi中开发实际的基于VisiBroker 的ORB多层应用体系的基本应用可以大胆的说已经够用了(如果有人反对我不介意),CORBA是一一个不断补充发展的标准,而且每种ORB产品又会对CORBA进行自己的描述,所以前面的一些IDL只是有一部分和OMG的定义有一定的区别,但是这不会影响到我们理解CORBA,当然必须说明的是前面的IDL描述都是完全符合VisiBroker的规范的。在C/S模式的程序设计之中,我们中绝大部分人是不会去考虑接口设计的,偶尔的出现也不会是采用我们开发多层系统这样的模式,所以刚刚接触多层系统的程序员要付出比C/S模式下设计大的多地精力来设计它,而且会拖延开发的周期,我一直在思考一个问题能不能避免这样的事情呢?或者说去谋求一个好的方法来改进我们的设计呢?在我看来拖延工期的问题主要表现在我们对于接口的确定上,接口的不确定因素体现在增加接口,修改接口,废止接口等等诸多问题上,设计接口我觉的类似与我们在设计ER图中的实体间的关系一样,如何平衡【服务――-中介―――客户】三者之间的关系是多层的首要问题,也是使得我们反复的罪魁祸首,在这里我想向大家推荐强大的Rational家族系列产品(Rose,SODA,ClearCase…..)我们可以使用这样的一些辅助工具来缩短我们的反复频率,在问题的分解中明确接口的设计方向与设计原则,对于拥有微软企业版开发套间的朋友可以利用Virtual Moduler工具来设计(这个工具是微软捆绑的ROSE产品,是一个标准的多层体系)在这里我不对如何使用他们来设计CORBA的接口进行描述,原因只有一个这是一个高级课题不属于<VisiBroker for Delphi>的范畴之中,我会在《面向CORBA的设计实践》中与大家共同探讨。 数据挖掘研究院
好了闲话就聊到这里,下面开始正体。
记得我在本文的第一小节中提到过CORBA DataMoudel Object,如果使用过这个对象的朋友一定清楚的了解单线程模式与多线程模式,也就是CORBA 3.3为大家提供了两种来至于TDataMoudel对象,进行的整体的封装,然而现在的CRB4.0为程序员提供了更大的灵活性 数据挖掘论坛
让我们自己来编写这样的两种不同的对象,显然后者可以让我们更广泛的扩展应用面,上次的例程就是一个多线程模式的例子,在讲解多线程模式之前我想还是让我们来看一下单线层模式的实例:
/*IDL*/
module TypeLibCRB
{ 数据挖掘论坛
interface InterfaceCRB; 数据挖掘论坛
数据挖掘论坛
interface InterfaceCRB 数据挖掘论坛
{ 数据挖掘论坛
any GetSQLData(in wstring Script, in boolean ExecutOrActive); 数据挖掘工具
}; 数据挖掘论坛
//定义一个发送客户执行的SQL,返回一个any类型
数据挖掘论坛
};
//XXX_Impl.pas 数据挖掘论坛
interface 数据挖掘交友
数据挖掘交友
uses 数据挖掘实验室
SysUtils, 数据挖掘实验室
CORBA,
TypeLibCRB_i, 数据挖掘论坛
TypeLibCRB_c 数据挖掘实验室
;
数据挖掘工具
type
TInterfaceCRB = class;
数据挖掘实验室
TInterfaceCRB = class(TInterfacedObject, TypeLibCRB_i.InterfaceCRB) 数据挖掘研究院
protected 数据挖掘研究院
public 数据挖掘交友
constructor Create; 数据挖掘实验室
function GetSQLData ( const Script : WideString; 数据挖掘交友
const ExecutOrActive : Boolean): Any; 数据挖掘交友
end; 数据挖掘交友
数据挖掘交友
数据挖掘研究院
implementation 数据挖掘交友
数据挖掘工具
uses UmCRBServer, UnCRBServer; 数据挖掘研究院
数据挖掘工具
constructor TInterfaceCRB.Create; 数据挖掘实验室
begin
inherited; 数据挖掘研究院
数据挖掘论坛
end; 数据挖掘论坛
数据挖掘实验室
function TInterfaceCRB.GetSQLData ( const Script : WideString; 数据挖掘实验室
const ExecutOrActive : Boolean): Any; 数据挖掘交友
数据挖掘研究院
begin 数据挖掘研究院
Form1.Memo1.Lines.Text:=Script; 数据挖掘交友
Result:=DataMCRB.GetData(Script,ExecutOrActive); 数据挖掘实验室
//调用TDataMoudel实例的方法请注意这个地方只有一个TDataMoudel实例
//下面的程序中会描述这个实例的方法定义 数据挖掘工具
end;
数据挖掘研究院
数据挖掘工具
initialization 数据挖掘研究院
数据挖掘工具
end. 数据挖掘研究院
/********************/ 数据挖掘实验室
/*动态创建数据实例的操作*/ 数据挖掘实验室
unit UmCRBServer; 数据挖掘论坛
数据挖掘工具
interface
数据挖掘论坛
uses 数据挖掘交友
SysUtils, Classes, DB, DBTables,Provider; 数据挖掘工具
数据挖掘工具
type 数据挖掘交友
TDataMCRB = class(TDataModule) 数据挖掘论坛
DatabCRB: TDatabase;
QueryCRB: TQuery; 数据挖掘实验室
DataSetPCRB: TDataSetProvider; 数据挖掘工具
private 数据挖掘论坛
{ Private declarations } 数据挖掘实验室
public 数据挖掘研究院
function GetData(Script:String;ExecuteOrActicve:boolean):OleVariant; { Public declarations } 数据挖掘研究院
end;
var 数据挖掘论坛
DataMCRB: TDataMCRB; 数据挖掘交友
function RunSQL(QueryX:TQuery;Script:String;ExecuteOrActive:boolean):boolean; 数据挖掘工具
implementation 数据挖掘工具
//这个代码中没有使用Session,也没有对事务进行控制,下一章节会给出一个使用Session的//例程,想一想这个方法的应用会有什么有点和缺点,如果愿意谈一谈請将您的想法发往我得//信箱 数据挖掘论坛
{$R *.dfm} 数据挖掘实验室
function RunSQL(QueryX:TQuery;Script:String;ExecuteOrActive:boolean):boolean; 数据挖掘实验室
begin 数据挖掘研究院
Result:=false;
with QueryX do 数据挖掘工具
begin 数据挖掘论坛
if Active then Active:=false; 数据挖掘论坛
SQL.Clear; 数据挖掘实验室
SQL.Text:=Script; 数据挖掘研究院
if ExecuteOrActive then 数据挖掘工具
ExecSQL else 数据挖掘研究院
Active:=true;
if not IsEmpty then
Result:=true;
end; 数据挖掘论坛
end; 数据挖掘交友
//这段代码我不讲解
{ TDataMCRB } 数据挖掘交友
数据挖掘研究院
function TDataMCRB.GetData(Script: String; 数据挖掘论坛
ExecuteOrActicve: boolean):OleVariant; 数据挖掘实验室
var 数据挖掘交友
MyQry:TQuery;
MyPrv:TDataSetProvider; 数据挖掘研究院
begin 数据挖掘论坛
try 数据挖掘实验室
MyQry:=TQuery.Create(self); 数据挖掘论坛
MyPrv:=TDataSetProvider.Create(self); 数据挖掘交友
MyQry.DatabaseName:=DatabCRB.DatabaseName; 数据挖掘交友
//注意如果使用TDataBase对象請将ShareHandle设为True; 数据挖掘论坛
MyPrv.DataSet:=MyQry; 数据挖掘交友
if RunSQL(MyQry,Script,ExecuteOrActicve) then 数据挖掘交友
Result:=MyPrv.DATA; 数据挖掘工具
finally 数据挖掘论坛
MyQry.Free; 数据挖掘工具
MyQry:=nil; 数据挖掘交友
MyPrv.Free; 数据挖掘论坛
MyPrv:=nil;
end; 数据挖掘论坛
end; 数据挖掘研究院
//动态创建数据集和数据提供者对象,在调用接口将数据返回给Client后释放动态创建的两//对象。这样可以避免在单线模式下客户端持久的拥有接口后的对象。
end. 数据挖掘研究院
/*****************************************/
/初始化CORBA实例,主单元 数据挖掘研究院
unit UnCRBServer; 数据挖掘论坛
interface 数据挖掘论坛
uses 数据挖掘实验室
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 数据挖掘实验室
Corba, TypeLibCRB_c, TypeLibCRB_i, TypeLibCRB_impl, TypeLibCRB_s, 数据挖掘论坛
StdCtrls; 数据挖掘研究院
type 数据挖掘研究院
TForm1 = class(TForm) 数据挖掘实验室
procedure FormCreate(Sender: TObject); 数据挖掘交友
private 数据挖掘工具
{ private declarations } 数据挖掘论坛
protected 数据挖掘工具
{ protected declarations } 数据挖掘论坛
MyCRB:InterfaceCRB;
procedure InitCorba; 数据挖掘实验室
public 数据挖掘论坛
{ public declarations } 数据挖掘论坛
end; 数据挖掘实验室
数据挖掘论坛
var 数据挖掘论坛
Form1: TForm1; 数据挖掘论坛
数据挖掘工具
implementation 数据挖掘工具
数据挖掘工具
{$R *.DFM} 数据挖掘论坛
数据挖掘工具
procedure TForm1.InitCorba; 数据挖掘工具
begin
CorbaInitialize; 数据挖掘实验室
MyCRB:=TInterfaceCRBSkeleton.Create("MyCRBServer",TInterfaceCRB.Create);
BOA.ObjIsReady(MyCRB as _Object);//CORBA服务就绪
end; 数据挖掘工具
数据挖掘论坛
procedure TForm1.FormCreate(Sender: TObject); 数据挖掘实验室
begin
InitCorba;//初始化调入 数据挖掘交友
end; 数据挖掘论坛
数据挖掘研究院
end.
/******************************************************/ 数据挖掘交友
/客户端程序 数据挖掘工具
nit UnClientMain; 数据挖掘工具
数据挖掘研究院
interface 数据挖掘论坛
数据挖掘研究院
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 数据挖掘研究院
Corba, TypeLibCRB_c, TypeLibCRB_i, Grids, DBGrids, DB, DBClient, StdCtrls;
type 数据挖掘论坛
TForm2 = class(TForm)
Edit1: TEdit;
Button1: TButton; 数据挖掘实验室
ClientDataSet1: TClientDataSet; 数据挖掘论坛
DataSource1: TDataSource; 数据挖掘交友
DBGrid1: TDBGrid; 数据挖掘实验室
procedure Button1Click(Sender: TObject); 数据挖掘研究院
procedure FormCreate(Sender: TObject); 数据挖掘论坛
private
{ private declarations } 数据挖掘工具
protected 数据挖掘论坛
/ myCRB:InterfaceCRB; 数据挖掘交友
数据挖掘交友
{ protected declarations }
public 数据挖掘实验室
{ public declarations } 数据挖掘工具
end; 数据挖掘交友
var 数据挖掘交友
Form2: TForm2; 数据挖掘研究院
implementation 数据挖掘工具
数据挖掘研究院
{$R *.DFM} 数据挖掘交友
数据挖掘交友
数据挖掘工具
数据挖掘交友
procedure TForm2.Button1Click(Sender: TObject);
begin 数据挖掘实验室
ClientDataSet1.Data:=myCRB.GetSQLData(Edit1.Text,false); 数据挖掘实验室
end; 数据挖掘实验室
procedure TForm2.FormCreate(Sender: TObject); 数据挖掘工具
begin
myCRB:=TInterfaceCRBHelper.Bind("MyCRBServer","127.0.0.1"); 数据挖掘交友
end;
end.
上面的程序让你无法使用ApplyUpdate方法来从客户端更新数据,如果要更新数据必须通过GetSQLData(SQL,True)来更新数据,相对来说客户端将不能使用数据感知类组件来编写插入删除,修改类程序,因为你的中间层的数据集与数据提供者不具有持久性,这就是下面代码使用DMPooler的精妙之处。
//
TDataModuleClass = class of TDataModule; // "class" reference 数据挖掘论坛
首先,由于客户请求数目的不确定性,我们必须为可能的请求提供一个用于存放独立实例请求单元的空间量(Pooler Size),假定我们考虑的可能有5个独立请求同时拥有这样持久对象,那么我们可以设定PoolSize=5,注意必须定义在全局的CONST中,因为每个对象是一个独立体,不过里也可以将这样的对象列入到TLIST对象中保存,当然还有更高级的构造方式,这些东西来源于程序员对Delphi的理解程度,例如:你可以将全部的实例使用TCollection类化处理,而不是使用下面的记录类型:
TPooledModule = record 数据挖掘工具
Module: TDataModule; 数据挖掘实验室
InUse: Boolean; 数据挖掘研究院
end; 数据挖掘实验室
当然这个地方使用的比较基础的方式来处理每一个ITEM,这个单元中包含了一个TDataModule实例,何一个表示这个实例是否被起用的开关量(我是这么命名的,当然这仅是基本的表达,而根据业务需求的规则需要自己来定义比此更好的比编写方式,而这个东西同样来源于对于OO概念的理解,和面向对象编程的经验的积累). 数据挖掘交友
当然,由于我们的客户对象的相互独立并确是一个持久的对象,那么也就是告诉我们整个对象池,是一个多线程的架构(如果是初次接触的朋友们最好先去读一下Thread).所以我们必须在对象的构造方法中申明为 数据挖掘研究院
constructor TModulePooler.Create; 数据挖掘论坛
begin 数据挖掘工具
IsMultiThread := True; 数据挖掘论坛
…… 数据挖掘交友
end; 数据挖掘研究院
如果请求被客户中断,或则实例由于异常而停止我们必须将这个实例终止,释放实例对象: 数据挖掘论坛
procedure TModulePooler.FreeModule(DataModule: TDataModule); 数据挖掘研究院
var 数据挖掘论坛
I: Integer; 数据挖掘实验室
Begin 数据挖掘论坛
……… 数据挖掘交友
for I := 0 to Length(FModules) - 1 do 数据挖掘工具
if FModules[I].Module = DataModule then 数据挖掘实验室
FModules[I].InUse := False;
ReleaseSemaphore(FSemaphore, 1, nil); 数据挖掘研究院
…….. 数据挖掘论坛
end; 数据挖掘研究院
那么,创建和释放的方法在我们写好已后,那么我们如何来构造这个单元的实体方法呢? 数据挖掘实验室
请看: 数据挖掘研究院
function TModulePooler.GetModule: TDataModule; 数据挖掘实验室
var 数据挖掘论坛
I: Integer; 数据挖掘交友
begin 数据挖掘工具
Result := nil; 数据挖掘实验室
if WaitForSingleObject(FSemaphore, 5000) = WAIT_TIMEOUT then 数据挖掘研究院
//设定延时响应,假定服务超时,那么我们将引发一个异常类,表示服务器太忙而未能响应请求。 数据挖掘实验室
raise Exception.Create("Server too busy"); 数据挖掘论坛
try
if Length(FModules) = 0 then 数据挖掘工具
//如果这个对象记录数组为空我们将创建这样一个动态的对象记录数组,即创建一个链表,每个对象作为其中的一个单元而存在,当然在实际的开发中我认为这种方法不是最好的,我会采用TStrings或则Tlist以及TCollections来存放单元,具体的使用我会在下一节给出 数据挖掘实验室
begin 数据挖掘工具
SetLength(FModules, PoolSize);
for I := 0 to PoolSize - 1 do 数据挖掘论坛
begin 数据挖掘工具
FModules[I].InUse := False; 数据挖掘工具
FModules[I].Module := FModuleClass.Create(Application);
end; 数据挖掘交友
end; 数据挖掘论坛
for I := 0 to Length(FModules) - 1 do
if not FModules[I].InUse then 数据挖掘工具
begin 数据挖掘工具
FModules[I].InUse := True; 数据挖掘工具
Result := FModules[I].Module; 数据挖掘论坛
Break; 数据挖掘论坛
end;
finally 数据挖掘论坛
FCSect.Leave; 数据挖掘工具
end; 数据挖掘实验室
//Check if we ran out of connections 数据挖掘工具
if not Assigned(Result) then
raise Exception.Create("Pool is out of capacity");
end; 数据挖掘论坛
在加载时创建 数据挖掘交友
initialization 数据挖掘研究院
ModulePooler := TModulePooler.Create; 数据挖掘工具
退出时释放 数据挖掘实验室
finalization 数据挖掘论坛
ModulePooler.Free; 数据挖掘交友
千万要记住检测对象是否存在,一定要在不再使用的时候释放持久对象,否则就会不断的堆砌,最终溢出哦! 数据挖掘研究院 可能是工作的原因,最近总是抽不出太多的时间来写这样的文章,在我看来已后基于C/S的软件将会越来越少,而绝大多数会聚集于微软的COM+体系中,这倒不是说COM+一定比CORBA优秀,而是COM+不要钱,而仅仅是需要一套WIN2000/XP,当然一向已C++为设计语言的朋友们可以参考很多的用C++写的资料,而Delphi的朋友们的资料少的可怜,建议还是学一点C++,我相信“真正的程序员用C++,聪明的程序员用Object Pascal,而大师[绝对优秀的程序师]是没有语言障碍的“,“有条件的用CORBA(因为跨平台),没有条件的用COM+(因为CORBA收费,COM+免费)”. 数据挖掘工具
下一节谈讨更高级的话题(对象定位技术与接口异常处理) 数据挖掘实验室 |