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。