kbmMW 5.06.20试用笔记
1.kbmMWConfiguration自动备份配置文件的问题还没有修正。
下面是以前写过的内容,再一次在新闻组中提出这个问题:
kbmMW提供一个强大的配置信息管理对象,前期译过这个对象的介绍,在使用过程中,发现一个问题, 就是TkbmMWCustomConfigurationStorage.BackupMaxCount属性,当设置为0时,也会生成配置信息的备份文件,在最新的kbmMW 5.05.11版本中,每运行一次就生成一个配置文件,对此,修正了代码。
打开单元文件 kbmMWGlobal,找到下面这个方法:
function kbmMWBackupFile, .... if not FileExists(AFile) then begin Result:=AFile; exit; end; if AMaxBackups<=0 then//判断AMaxbackups来决定是否生成备份文件: begin Result:=AFile; exit; end; ...
TSysConnectionParam = class//(TkbmMWConfigurableObject) private [kbmMW_Config('QueryServiceVersion',mwcdReadWrite)] FQueryServiceVersion: string; [kbmMW_Config('QueryServiceName',mwcdReadWrite)] FQueryServiceName: string; [kbmMW_Config('SessionName',mwcdReadWrite)] FSessionName: string; [kbmMW_Config('FileServiceVersion',mwcdReadWrite)] FFileServiceVersion: string; [kbmMW_Config('FileServiceName',mwcdReadWrite)] FFileServiceName: string; public property SessionName: string read FSessionName write FSessionName; property QueryServiceName: string read FQueryServiceName write FQueryServiceName; property QueryServiceVersion: string read FQueryServiceVersion write FQueryServiceVersion; property FileServiceName:string read FFileServiceName write FFileServiceName; property FileServiceVersion:string read FFileServiceVersion write FFileServiceVersion; end;
这个TSysConnectionParam不从TkbmMWConfigurableObject继承,否则在android平台,出这个错误:Type (TSysConnectionParam@6260DC60) not registered as a known type.
说明TkbmMWConfigurableObject还是存在跨平台的问题。
既然不能从TkbmMWConfigurableObject继承,怎么实现一个自动读取与保存的配置对象呢,按Configuration REST easy with kbmMW #7。
为配置对象重载AfterConstruction与BeforeDestruction方法,实现自动保存与读取配置对象!
public procedure AfterConstruction; override; procedure BeforeDestruction; override;
{ TSysConnectionParam } procedure TSysConnectionParam.AfterConstruction; begin inherited; Config.ReadConfig(Self); end; procedure TSysConnectionParam.BeforeDestruction; begin Config.WriteConfig(Self); inherited; end;
现在,TSysConnectionParam的实例在建立与释放时,就能自动读取与保存参数,在Win32及Android下测试通过。
虽然TkbmMWConfigurableObject存在跨平台问题,但用上面方法来跳过,也是很好的方案,毕竟可以跨平台使用kbmMWConfiguration Frame!
procedure Tmainform.Button3Click(Sender: TObject); begin kbmMWClientQuery1.Close; kbmMWClientQuery2.Close; kbmMWClientQuery1.Open; kbmMWClientQuery2.Open; kbmMWClientQuery1.AppendRecord([1,'1']); kbmMWClientQuery1.AppendRecord([1,'2']);//t1表在数据库中主键重复错 kbmMWClientQuery2.AppendRecord([1,'1']); kbmMWClientQuery2.AppendRecord([1,'2']);//t2表在数据库中主键重复错 kbmMWClientTransactionResolver1.Resolve([kbmMWClientQuery1,kbmMWClientQuery2]); end;
上面是测试代码,同时提交两个ClientQuery,每个表都有主键重复错误,造成提交失败的场景,这时候,客户端会产生异常:stream read error.
已经反馈到官方新闻组,但作者还让我写个demo,已经发给他,等处理。注意:这个问题在上一版本中就存在。
4.更新主键遇到的问题
这个是朋友在学习过程中遇到的,整理出测试项目,大体情况是这样的:
现在有表t1,FID是主键,假设有如下记录
FID FName
1 1
2 2
把第一条记录,FID改成2,提交,这时候主键重复,提交失败,这时候kbmMW的工作结果是对的
FID FName
1 1
2 2
现在把第一条记录的FID改成3,提交,这时候没有了主键重复问题,提交成功,这时候kbmMW的工作结果也是对的。
FID FName
3 1
2 2
现在把第一条记录的任务字段改变值,如FName改成2,提交失败,这个结果不对的。问题就在这里。
FID FName
3 2
2 2
这是按上面的测试方法写的代码,重显问题:
procedure Tmainform.Button4Click(Sender: TObject); begin //这是一个bug Label1.Caption := ''; Memo1.Lines.Clear; // 删除所有记录 kbmMWClientQuery1.Close; kbmMWClientQuery1.Open; kbmMWClientQuery1.DeleteRecords; kbmMWClientQuery1.Resolve; kbmMWClientQuery1.AppendRecord([1, '1']); kbmMWClientQuery1.AppendRecord([2, '2']); kbmMWClientQuery1.Resolve; // keyfield // // 1,2 2,2 3,2 3,1 // 2,2 2,2 2,2 2,2 // error ok error kbmMWClientQuery1.Close; kbmMWClientQuery1.Open; kbmMWClientQuery1.First; kbmMWClientQuery1.Edit; kbmMWClientQuery1.FieldByName('fid').AsInteger := 2;//主键重复 if not kbmMWClientTransactionResolver1.Resolve([kbmMWClientQuery1]) then begin DataSource3.DataSet := kbmMWClientQuery1.InfoTable; Label1.Caption := kbmMWClientQuery1.InfoTable.FieldByName('kbmMW_ErrorMessage').AsString; Memo1.Lines.Add('Step 1: Modify the primary key to generate an error, the submission failed,it''s right. '+kbmMWClientQuery1.InfoTable.FieldByName('kbmMW_ErrorMessage').AsString); end; kbmMWClientQuery1.First; kbmMWClientQuery1.Edit; kbmMWClientQuery1.FieldByName('fid').AsInteger := 3;//设置主键不重复 if not kbmMWClientTransactionResolver1.Resolve([kbmMWClientQuery1]) then begin DataSource3.DataSet := kbmMWClientQuery1.InfoTable; Label1.Caption := kbmMWClientQuery1.InfoTable.FieldByName('kbmMW_ErrorMessage').AsString; Memo1.Lines.Add('Step 2: Modify the primary key to resolve the error and submit successfully,it''s right. '+kbmMWClientQuery1.InfoTable.FieldByName('kbmMW_ErrorMessage').AsString); end else begin Memo1.Lines.Add('Step 2: step 2:Modify the primary key to resolve the error and submit successfully,it''s right.'); Label1.Caption := 'Resolve OK.'; end; kbmMWClientQuery1.First; kbmMWClientQuery1.Edit; kbmMWClientQuery1.FieldByName('fname').AsString := '1';//无法修改这条记录了!这是bug. if not kbmMWClientTransactionResolver1.Resolve([kbmMWClientQuery1]) then begin DataSource3.DataSet := kbmMWClientQuery1.InfoTable; Label1.Caption := kbmMWClientQuery1.InfoTable.FieldByName('kbmMW_ErrorMessage').AsString; Memo1.Lines.Add('Step 3: Modify any field and cannot submit,it''s bug. '+kbmMWClientQuery1.InfoTable.FieldByName('kbmMW_ErrorMessage').AsString); end else begin Label1.Caption := 'Resolve OK.'; end; end;
5.洞主测试rest上传文件服务需要修正下面两个方法,并已经提交给作者,等待修正。
function TkbmMWHTTPMultiPart.GetAsBytes:TBytes; var p:PByte; i:integer; begin SetLength(Result,FDataLength); p:=PByte(FOwner.FStream.Memory); inc(p,FDataOfs); Move(p^,Result[0],FDataLength); end; function TkbmMWHTTPMultiPart.GetAsString:string; begin Result:=TkbmMWPlatformMarshal.UTF8Decode(GetData,FDataLength); end;
这是xalion写的上传文件服务的例子,必须学习了!
6.Scheduler存在的问题
WaitRuns: FileService的SameFile方法,不等取得本地文件的CheckSum,造成执行结果错误,这个问题在5.04.30解决过,不知为何又回来了,问题出在WaitRuns上,不等Scheduler执行。
SynchronizedAfterRun:利用Scheduler在线程中执行一个查询,然后在SynchronizedAfterRun使用查询回来的数据集,偶尔会出现找不到字段的问题。感觉与WaitRuns存在的问题有关系。
7.Q友冰雨反应Resolve问题KbmMW V5.06.2,修改数据,kbmwclntrnsctnrslvrTR.Resolve([kbmwclntqryMain]),保存的时候,变成insert语句,导致主键重复。KbmMW V5.06.1 beta版本已经发现了这个问题,退回前一个正式版,目前正常了。