kbmMW CopyRawRecords 用法

复制一个ClientQuery数据集到另外一个ClientQuery,我们应该怎么做?并注意什么呢?

kbmMW为我们提供了好几个方法,有LoadFromDataSet,CopyRawRecords,CopyRecords等。查看源码,应该是CopyRawRecords最有效率,但使用过程中遇到好几个莫名的问题,也是按照原码,最后用下面的写法,正确实现利用CopyRawRecords在ClientQuery间复制记录。下面是从项目中提取的代码,测试通过。

ClientQuery.DisableControls;
ClientQuery.DisableEvents;
origEnableVersioning := ClientQuery.EnableVersioning;
OrigAutoPopulate := ClientQuery.AutoPopulateOnOpen;
OrigAutoFieldDefs := ClientQuery.AutoFieldDefsOnOpen;
ClientQuery.AutoPopulateOnOpen := false;
ClientQuery.AutoFieldDefsOnOpen := mwafoNever;
ClientQuery.EnableVersioning:=False;
try
   FInternalClientQuery.LoadFromStreamViaFormat(c.ResultStream, bsf);
   if not ClientQuery.Active then
   begin
        ClientQuery.CreateTableAs(FInternalClientQuery, [mtcpoStructure]);
        ClientQuery.Open;
        ClientQuery.CopyRawRecords(FInternalClientQuery,FInternalClientQuery.RecordCount,[]);
//      ClientQuery.LoadFromDataSet(FInternalClientQuery, [mtcpoStructure]);
   end
   else
   begin
        Log.TimeStart('CopyRawRecords');
        ClientQuery.CopyRawRecords(FInternalClientQuery,-1,[mwucAutoUTF8,mwucStringsIsUnicode,mwucAutoParamUTF8]);
//                Log.TimeLapse('CopyRawRecords','CopyRawRecords用时:');
//                ClientQuery.LoadFromDataSet(FInternalClientQuery, [mtcpoAppend]);
         Log.TimeEnd('CopyRawRecords','CopyRawRecords用时:');
   end;

 finally
     ClientQuery.EnableVersioning:=origEnableVersioning;
     ClientQuery.AutoPopulateOnOpen := OrigAutoPopulate;
     ClientQuery.AutoFieldDefsOnOpen := OrigAutoFieldDefs;
     ClientQuery.EnableEvents;
     ClientQuery.EnableControls;
  end;

先说说实际的应用场景,ClientQuery是一个没有字段定义的数据集,当客户端从服务端取得生成的数据流,并加载到FInternalClientQuery中,然后再复制到ClientQuery中,当第一次ClientQuery无字段定义时,我们需要从FInternalClientQuery复制结构给ClientQuery。当第二次取服务端取得FInternalClientQuery内容时,我们再追加到ClientQuery中,这时候,就不用再管他的结构了。

可以你要问,这么做干嘛?还不是为了分页查询,一页一页的为ClientQuery加载记录。

当复制结构时,要做二件事:

ClientQuery.AutoPopulateOnOpen := false;//Open时不自动填充记录
ClientQuery.AutoFieldDefsOnOpen := mwafoNever;//Open时不自动取得表结构

加载记录时,还要做二件事:

ClientQuery.DisableEvents;//屏蔽触发数据集事件,如OnNewRecord...
ClientQuery.EnableVersioning:=False;//因为CopyRawRecords内部已经处理了,这里可以不再处理

然后,用CreateTableAs建立结构,并打开ClientQuery,再调用CopyRawRecords复制记录到ClientQuery:

ClientQuery.CreateTableAs(FInternalClientQuery, [mtcpoStructure]);
ClientQuery.Open;
ClientQuery.CopyRawRecords(FInternalClientQuery,FInternalClientQuery.RecordCount,[]);

当ClientQuery有结构时,可以直接把FInternalClientQuery内容追加到ClientQuery中:

ClientQuery.CopyRawRecords(FInternalClientQuery,-1,[mwucAutoUTF8,mwucStringsIsUnicode,mwucAutoParamUTF8]);

我做了效率测试,CopyRawRecords比LoadFromDataSet快三倍以上。

总结来说,为了使用CopyRawRecords,我们要先建立好ClientQuery的结构,为了按源DataSet创建结构,可以使用CreateTableAs方法,但使用这个方法时,我们要设置AutoPopulateOnOpen及AutoFieldDefsOnOpen两个属性,不允许自动填充记录及不自动获取结构,另外,使用CreateTableAs后,ClientQuery是不Open的,需要手工Open。

原文地址:https://www.cnblogs.com/kinglandsoft/p/9220840.html