DataSnap基础(3)

2020-06-05 11:11

procedure TForm2.ClientDataSet1AfterPost(DataSet: TDataSet); begin

ClientDataSet1.ApplyUpdates(0); end;

如果发生了更新错误,将会触发TClientDataSet的OnReconcileError事件,更多信息见3.2.3

手动方式发生更新也是使用TClientDataSet的ApplyUpdates方法.但是这时方法不在OnAfterInsert,OnAfterPost和OnAfterDelete事件中执行.而是我们添加一个按钮让用户显示的提交更新. procedure TForm2.btnUpdateClick(Sender: TObject); begin

ClientDataSet1.ApplyUpdates(0); end;

自动提交的好处当然用户不会忘记将变更保存回服务端.然而,缺点是无法提供Undo能力.一旦提交数据就更新回了服务器.另外,如果使用手动提交,所有变更保存在客户端---TClientDataSet

组件的内存中.这样就允许用户Undo部分变更:使特定记录或全部记录放弃更新.点击更新按钮显示调用ApplyUpdate方法.可能会导致用户忘记提交修改数据.我们应该在窗口关闭时添加代码检查TClientDataSet中是否还有未提交数据(检查TClientDataSet.ChangeCount属性).

3.2.3. RECONCILE ERRORS

TClientDataSet.ApplyUpdates方法有一个参数:应用更新时允许发生的最大错误数量.如果有

两个客户端连接到了DataSnap服务端,获取Employees数据并同时修改了第一行数据.依据目前为止我们的实现,两个客户端都会使用TClientDataSet的ApplyUpdates将数据变更到DataSnap服务端.如果都将ApplyUpdates的参数MaxErrors设置为0,则第二个客户端的提交将会停止.第二个客户端应该使用一个大于0的参数指定允许的错误/冲突数.然而,即使第二个客户端将MaxErrors设置为-1(不管有多少错误发生都继续提交后面的更新记录),都不会提交被第一个用户更新过的记录.换句话说,你需要执行一系列冲突处理来解决这些更新已经被更新的记录或列的冲突问题.幸运的是,Delphi提供了一个很强大的对话框来处理这个问题.当在DataSnap客户端需要做一些冲突处理时,都可以使用这个对话框(或自己实现,但最终都是处理冲突问题).

使用Delphi提供的功能,File.New.Other,在Delphi文件子目录中选择Reconcile Error对话框图标.选中这个图标点击OK,保存为RecError.pas,加入到DataSnapClient项目.这个单元包括了定义和实现更新错误对话框.来解决数据库更新错误. ReconcileErrorForm窗体实例将按需要动态创建.那么如何使用这个特殊的ReconcileErrorForm窗体呢? 好,其实很简单.对于每个没有成功更新的记录,都会触发TClientDataSet的OnReconcileError事件.定义如下: procedure TForm2.ClientDataSet1ReconcileError(DataSet: TClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction);

这个事件处理程序与四个参数,第一个是抛出错误的TClientDataSet,第二个参数是引发错误冲突的原因,第三个参数是更新类型UpdateKind(insert,delete,modify),第四个参数是你要如何处理冲突.可以返回如下枚举类型值: - raSkip:不更新这条记录,但在变更日志中保留未提交的变更,下次提交在试. -raAbort:取消记录冲突处理..

-raMerge:将更新记录与远程数据库记录合并,仅在客户端变更修改过的远程字段 -raCorrect:使用正确的值替换更新记录,这需要用户介入. -raCancel:对本记录的修改全部放弃.回到初始值状态.

-raRefresh:对本记录修改全部放弃,但重新加载当前数据库的记录值.

关于ReconcileErrorForm不需要考虑全部执行选项.只需要做两件事件.一,在DataSnap客户端主窗体中 引用错误处理对话框单元.二,在OnReconcileError事件中写一行代码调用ReconcileErrorForm单元中的 HandleReconcileError全局函数. HandleReconcileError函数也有四个同样的参数,只需要按顺序传递即可. 如下所示:

procedure TFrmClient.ClientDataSet1ReconcileError(DataSet: TClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction);

begin

Action := HandleReconcileError(DataSet, UpdateKind, E) end;

3.2.4. 示范冲突错误

现在最大的问题是:实际工作中如何使用的冲突处理?为了测试,需要两个或更多DataSnap客户端同时运行.为使用当前的客户端和服务端进行测试,需要执行如下步骤: -启动服务端应用程序

-启动第一个客户端应用程序,点击链接按钮,获取数据 -启动第二个客户端应用程序,点击链接按钮,获取数据

-使用第一个客户端应用程序,修改第一行数据的FirstName列 -使用第二个客户端应用程序,修改第一行数据的FirstName列 -在第一个客户端应用程序中点击更新按钮

-在第二个客户端应用程序中点击更新按钮,这时将会发生一个或多个错误.因为第一个应用程序已经修改了同一行的同一个列.引起冲突. OnReconcileError被触发.

-进入更新错误对话框,现在可以处理冲突(忽略(Abort),取消(Abort),合并(Merge),更正(Correct),取消 (Cancel),更新(Refresh)).测试一下Skip和Cancel的不同,及Correct,Refresh和Merge的不同.

Skip移动到下一行记录,忽略更新请求.但其更新将保留在更新日志中.Cancel也忽略更新请求同时清除本记录所有以前的更新记录.

Refresh清除本记录所有的变更记录,并将数据库中的值作为当前记录的值.Merge试图将数据库记录和更新记录合并.将变更提交到数据库.更新和合并的记录都不会再进行处理,记录已经与数据库同步.

Correct是一个强大的选项,在事件处理中给你一个指定更新记录值的机会.需要写代码或弹出对话框指定新值.

3.3. DATASNAP 数据库部署

部署一个使用数据库的DataSnap服务需要比部署一个简单DataSnap服务的步骤要多些.客户端,没什么变化,还是一个瘦客户端,如将MidasLib加入到了项目引用就仅需部署一个单一的可执行文件.

服务端,必须部署数据库驱动.及所选数据库依赖的驱动和文件.使用DBX4,确保发布 TSQLConnection组件和dbxconnections.ini及dbxgrivers.ini文件(可在C:\\Documents and

Settings\\All Users\\ Documents\\RAD

Studio\\dbExpress\\7.0 directory on Windows XP or in the C:\\Users\\Public\\Documents\\RAD Studio\\dbExpress\\7.0中找到). dbxdrivers.ini文件指定所用驱动, DriverPackageLoader及

MetaDataPackageLoader(通常指向同一个包).对于BlackFishSQL,使用的DBXClientDriver140.bpl文件,需要 部署到服务端.更多关于部署BlashFishSQL信息见RAD Studio\\7.0 目录下的deploy_en.htm文件.

3.4. 重用已有的远程数据模块

如果你有一个远程数据模块类,也可以将其组合到新的DataSnap项目中来.但是必须要牺牲一些特性,尤其 是引入了COM.

首先,如果有一个你要迁移的DataSnap服务应用程序,而不仅仅是一个远程数据模块,你需要使用命令行

/unregister注销DataSnap服务.不做这步将无法注销远程数据模块.在远程数据模块单元,移除initialization区 域.如果还希望这个单元在D2007及一下版本重用,可以使用编译开关:

{$IF CompilerVersion >= 20}

initialization

TComponentFactory.Create(ComServer, TRemoteDataModule2010, Class_RemoteDataModule2010, ciMultiInstance, tmApartment); {$IFEND} end.

从项目中移除UpdateRegistry函数或用编译开关修饰:

{$IF CompilerVersion >= 20}

class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override; {$IFEND}

最重要的变更—将项目转换为无COM依赖的DataSnap服务.-及移除类型库(.ridl文件)和类型库导入单元.这 无法通过编译器开关修改,因此需要为D2007及一下版本和D2009及以上版本分别生成一个项目文件.在 TRemoteDataModule类中放一个TDSServerClass组件.最后,将所有的自定义方法都转到 TRemoteDataModule单元的public节中.

4. DATASNAP 过滤器[FILTER]用法

本节将说明过滤器工作原理,及如何使用已存在的过滤器(如压缩)或创建新的DataSnap过滤器.DataSnap

过滤器是一个特殊的DLL,拦截通讯流,在整个过滤器链中操作通讯流.所以本例中我们可以使用压缩和解压缩 过滤器,或记录压缩等.

必须在客户端和服务端指定过滤器.在服务端,必须指定TDSTCPServerTransport组件的过滤器属性列表. 在客户端,必须在客户端项目中引用过滤器单元文件.对于客户端这就足够了,因为每个DataSnap过滤器都会 自动注册.

当处理OnConnect事件时,可以检查用于连接的已注册的过滤器,例如使用自定义的日志函数输入日志信息,

procedure TServerContainer1.DSServer1Connect(DSConnectEventObject: TDSConnectEventObject); Var i: Integer; begin

LogInfo(\for i:=0 to DSConnectEventObject.Transport.Filters.Count-1 do LogInfo(\

DSConnectEventObject.Transport.Filters.GetFilter(i).Id); end;

4.1. ZLIBCOMPRESSION FILTER

作为范例,我们使用已随D2010提供的DataSnap过滤器.可用于在客户端和服务端压缩数据流.这里说的 ZlibCompression过滤器可以在DbxCompressionFilter单元找到.

TDSTCPServer和TDSHTTPService组件都有一个TTransportFiltersCollection类型的Filters属性.点击Filters 属性后面的按钮,编辑过滤器列表.在这个对话框中,我们可以加一个新的TTransportFilterItem,然后在Object Inspector中设置FilterID和一些属性.在下拉框中可以找到Delphi2010提供的ZLibCompression过滤器.

注意除了设置服务端TDSTCPServerTransport组件Filters属性外,也需要在客户端指定一个相应的过滤器 (压缩请求解压缩应答).这时,我们进需要将DbxCompressionFilter单元引用到ClientForm.其将自动注册一个 TTransportCompressionFilter并与服务端通讯.

如果没有在客户端添加DbxCompressionFilter单元引用,运行客户端后将会抛出异常信息:


DataSnap基础(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:食品物性学习题(附答案)

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: