摘要:MIDAS 中动态强制约束编程

                                                              MIDAS 中动态强制约束编程

作者: 陈一蛟
引言

 
  一个用来区分 MIDAS 与其他分布式数据库解决方案的特征就是,MIDAS 支持动态数据约束(constraints)功能。这些动态约束可以控制由 AppServer 到瘦客户端的分布式数据的外观、业务确认规则、是否显示等等功能。作者(John Kaster)认为这是分布式数据库需具备的一个非常重要的特征。
 
MIDAS 数据包(Data Packets)概述
  先介绍一下MIDAS 数据包(Data Packets)格式的详细特征,MIDAS 数据包(Data Packets)是一个独立于语言和中立传输(transport-neutral)的二进制流格式数据,他包括元数据(metadata), 约束(constraints), 数据(data), 和deltas。
  元数据是用来描述按照 APPSERVER 来分布的数据集。 MIDAS 2,3 支持嵌套数据集,因此单个数据包能够包含一个乃至于多个数据集的信息。约束是用来校验和显示数据集中的每个栏位的相关业务规则。Data 是数据集的实际数据栏位和记录数。Deltas 记录客户端的数据修改的 Log ,且是属于自动维护和传送到 AppServer中的。
MIDAS 数据栏位约束

  数据栏位约束是在 AppServer 与客户程序之间传播,可以快速修改业务规则,非常简便的发布新的客户程序,基于服务器端的业务规则,可以自动强制应用于客户程序,从而增强了分布式应用系统的生存周期以及系统的可维护性。
  如果没有充分的理由,应在客户端强迫执行基于服务器端的业务规则,这样将会提供应用系统的可靠性和数据的准确性,因为有问题的数据包会立即被客户程序检测到,所以应该培养正确的使用数据值和减少无效数据的网络回路的习惯。简单一点说,数据约束能让你快速构建分布式系统,及时响应相关修改要求和提高系统的可靠性
  MIDAS 2、3 数据包能够自动的由 AppServer 到客户端传递以下数据栏位属性:
Constraint Property Description
ConstraintErrorMessage Message to display if data for the field if not valid.
  Example: CustNo cannot be blank
CustomConstraint Constraints to place on the validation of the field. Expressions
  can be used for this constraint.
  Example: CustNo IS NOT NULL
DisplayFormat Controls formatting of the field for display
DisplayLabel Used as the data field's default column heading.
  Example: Customer #

EditMask Used for customizing data entry for the field.
  Example: 0000

MaxValue The maximum value of a numeric field
MinValue The minimum value of a numeric field
Visible A boolean value indicating whether the field should be visible in
  a grid by default

实现约束编辑服务器(Constraint Editor Server)
  只要客户连接到 MIDAS Server ,相关RDM(remote data module)就会自动创建并提供给客户来访问Server约束编辑服务器(ConstraintSvr.exe)在第一次使用这些RDM时会去获取 provider 的列表和包含在这些provider 中栏位约束。ConstraintSvr 也同样为编辑每个provider中的栏位约束提供一个用户接口和为每个应用实例保存更改结果。
  在更改结果保存后(在系统运行期),客户程序只需要简单的重新连接的 AppServer,获取一个新的数据包,此包中包含新的业务约束。
变量角色(A Cast of Variants)
  开始建立一个能够提供运行期编辑数据约束的应用程序,只需要做一点点代码定制。Screen 对象有一个属性可以列出一个应用程序中的所有数据模块(data modules),同样我们能通过检查此属性来建立包含在数据模块中的Provider 的列表。此 Provider 名列表是通过一个变量类型从数据模块中输出,同样也需要通过适当的Delphi 类型来接收数据模块的 Provider 命名。代码如下:
{ Copyright (c) 1999 - 2000 by John Kaster, Dan Miser and Louis Kleiman }
procedure GetProviderList( ProviderList : TStrings );
var

  ProviderNames : OLEVariant;
  I : Integer;

  DataSet : TDataSet;
  GenObject : TComponent;
begin

  if (Screen.DataModuleCount = 0) then
  Raise Exception.Create( 'No data modules are active.' );
  ProviderList.Clear;

  { Get the list of all providers for the first data module.
  All instances of the data module are probably the same. }
  ProviderNames := IConstraints(TConstraints(Screen.DataModules[0])).
  AS_GetProviderNames;
  for I := VarArrayLowBound(ProviderNames, 1) to
  VarArrayHighBound(ProviderNames, 1) do
  begin

  { Retrieve the component matching the provider name }
  GenObject := Screen.DataModules[0].FindComponent(ProviderNames[I]);
  if (GenObject is TDataSetProvider) then
  DataSet := TDataSetProvider(Screen.DataModules[0].
  FindComponent(ProviderNames[I])).DataSet
  else if (GenObject is TDBDataSet) then
  DataSet := TDataSet(Screen.DataModules[0].
  FindComponent(ProviderNames[I]))
  else

  DataSet := nil;
  { Add it to the list of providers, attaching the Dataset if assigned }
  ProviderList.AddObject(ProviderNames[I], DataSet);
  end; { for }

end; { GetProviderList() }
接收约束内容

  现在从RDM的实例获取 provider 列表,其他的都是一些传统的 Delphi 代码。通过一个列表框元件来显示Provider ,通过另一个列表框元件来显示每个提供者的栏位约束值。 Provider列表框元件命名为lbProviders。代码如下:
procedure TFormConstraintsEditor.lbProvidersClick(Sender: TObject);
var

  DataSet : TDataSet;
  I : Integer;

  SaveActive : Boolean;
begin

  lbFields.Clear;
  DataSet := TDataSet(lbProviders.Items.Objects[lbProviders.ItemIndex]);
  if Assigned(DataSet) then
  begin

  SaveActive := DataSet.Active;
  DataSet.Open;

  try
  for I := 0 to DataSet.FieldCount - 1 do
  lbFields.Items.AddObject(DataSet.Fields[I].FieldName,
  DataSet.Fields[I]);

  finally
  DataSet.Active := SaveActive;
  end; { try...finally }
  end; { if }

end;
编辑约束内容值

  现在使用编辑元件来为所选的栏位赋值。拖放这些控件到表单上,然后在下面的click 事件中将相应的选取的栏位的约束属性值赋值给编辑元件。 字段栏位列表框元件命名为lbFields 。代码如下:
procedure TFormConstraintsEditor.lbFieldsClick(Sender: TObject);
var

  Field : TField;
begin

  Field := TField(lbFields.Items.Objects[lbFields.ItemIndex]);
  if Assigned(Field) then
  begin

  edErrorMessage.Text := Field.ConstraintErrorMessage;
  edCustomConstraint.Text := Field.CustomConstraint;
  edDisplayLabel.Text := Field.DisplayLabel;
  edEditMask.Text := Field.EditMask;
  edDisplayFormat.Text := '';
  edMinValue.Text := '';
  edMaxValue.Text := '';
  cbVisible.Checked := Field.Visible;
  if Field is TNumericField then
  begin

  with Field as TNumericField do
  edDisplayFormat.Text := DisplayFormat;
  if Field is TFloatField then
  with Field as TFloatField do
  begin

  edMinValue.Text := FloatToStr( MinValue );
  edMaxValue.Text := FloatToStr( MaxValue );
  end

  else if Field is TBCDField then
  with Field as TBCDField do
  begin

  edMinValue.Text := FloatToStr( MinValue );
  edMaxValue.Text := FloatToStr( MaxValue );
  end

  else if Field is TIntegerField then
  with Field as TIntegerField do
  begin

  edMinValue.Text := IntToStr( MinValue );
  edMaxValue.Text := IntToStr( MaxValue );
  end

  else if Field is TLargeIntField then
  with Field as TLargeIntField do
  begin

  edMinValue.Text := IntToStr( MinValue );
  edMaxValue.Text := IntToStr( MaxValue );
  end;

  end
  else if Field is TDateTimeField then
  with Field as TDateTimeField do
  edDisplayFormat.Text := DisplayFormat;
  end; { if }

end;
提交已编辑的约束值

  在给字段栏位约束赋给了相应的值后,需提交应用这些约束值。代码如下:
procedure TFormConstraintsEditor.actApplyExecute(Sender: TObject);
var

  Field : TField;
begin

  Field := TField(lbFields.Items.Objects[lbFields.ItemIndex]);
  if Assigned(Field) then
  begin

  Field.ConstraintErrorMessage := edErrorMessage.Text;
  Field.CustomConstraint := edCustomConstraint.Text;
  Field.DisplayLabel := edDisplayLabel.Text;
  Field.EditMask := edEditMask.Text;
  Field.Visible := cbVisible.Checked;
  if Field is TNumericField then
  begin

  with Field as TNumericField do
  DisplayFormat := edDisplayFormat.Text;
  if Field is TFloatField then
  with Field as TFloatField do
  begin

  MinValue := StrToInt( edMinValue.Text );
  MaxValue := StrToInt( edMaxValue.Text );
  end

  else if Field is TBCDField then
  with Field as TBCDField do
  begin

  MinValue := StrToInt( edMinValue.Text );
  MaxValue := StrToInt( edMaxValue.Text );
  end

  else if Field is TIntegerField then
  with Field as TIntegerField do
  begin

  MinValue := StrToInt( edMinValue.Text );
  MaxValue := StrToInt( edMaxValue.Text );
  end

  else if Field is TLargeIntField then
  with Field as TLargeIntField do
  begin

  MinValue := StrToInt( edMinValue.Text );
  MaxValue := StrToInt( edMaxValue.Text );
  end;

  end
  else if Field is TDateTimeField then
  with Field as TDateTimeField do
  DisplayFormat := edDisplayFormat.Text;
  end; { if }

end;
  现已创建了 ConstraintSvr 的主要代码,详细代码可以下载。
创建强制约束的客户程序

  客户程序比创建服务器程序简单多拉,因为他只需要简单的接收一个修改后的数据包,而无须有编写Server 的知识。这是一个非常完美和强劲的动态约束程序示例:我们只需要在服务器端修改相关业务而无须修改客户程序,也无须发布新的客户程序。
  通过以下步骤建立客户端程序:
  拖一个 DCOMConnection 元件
  设置: RemoteServer=ConstraintSvr.Constraints
  拖一个 ClientDataset 元件
  设置: RemoteServer=DCOMConnection1
  设置: ProviderName=prvCustomer
  拖一个 DataSource

  设置: DataSet=ClientDataset1
  拖一个 DBNavigator

  设置: DataSource=DataSource1
  拖一个 Button

  设置: Name=btnOpen
  双击 button 建立 click 事件,btnOpenClick 事件代码如下:
procedure TFormConstraintClient.BtnOpenClick(Sender: TObject);
begin

  if ClientDataSet1.Active then
  ClientDataSet1.Close;
  ClientDataSet1.Open; { Refresh the dataset }
  BtnOpen.Caption := '&Reopen';
end;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值