加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi – 如何创建通用REST调用

发布时间:2020-12-15 09:51:35 所属栏目:大数据 来源:网络整理
导读:使用Delphi Seattle.我有一个应用程序,可以进行各种REST调用.其中一些调用可能通过 JSON返回10-20行,而其他调用可能返回30-40,000行.我已将我的REST服务器设置为以1,000个批量返回行.当数据回到我的客户端时,我使用RestDataAdapater,DataSource和Client Data
使用Delphi Seattle.我有一个应用程序,可以进行各种REST调用.其中一些调用可能通过 JSON返回10-20行,而其他调用可能返回30-40,000行.我已将我的REST服务器设置为以1,000个批量返回行.当数据回到我的客户端时,我使用RestDataAdapater,DataSource和Client Data Set来公开数据,就像它是本地表一样.这部分似乎工作正常.如果我们在1000行的末尾,那么我更改URL,并请求下一批1,000行.

我的挑战:我想抽象这个,以便一个例程可以处理所有场景(至少对于GET调用).棘手的部分是如何处理数据源/客户端数据集1,000行问题?一个例子可能有助于澄清……我希望能够执行这样的事情……

...
genericREST_Get(baseURL,resource,suffix);  // This would actually execute the REST call,where the components are in Datamodule DM1.
while not dm1.ds_Generic.DataSet.Eof do
        begin
       ... some kind of processing
       dm1.ds_Generic.DataSet.Next;
        end;

如何处理超过1000行阈值?当我的调用程序(如上所示)从第1000行到1001时,REST API需要从服务器请求下一组1000行.虽然我知道如何做到这一点,但我不知道该怎么做.我希望“获取下一个1000行”在通用例程中(也就是genericREST_Get例程).我不希望每个调用例程都必须处理它.

假设所有例程都只能向前移动,而不是向后移动.

解决方法

以下是您可以考虑的几个选项:

1)获取所有数据
对于大多数应用程序来说,内存中没有30-40,000行.即使你需要进行多次休息调用来获取数据,你也可以预先做到.如果您总是要遍历所有数据,那么如果您在循环中或在循环内部获取它,时间将是相同的:

repeat
    PartialData := genericREST_Get(baseURL,suffix);
    // CopyDataSet is actually a FireDac method that I don't see on ClientDataSet
    // Basically just .Append and copy all fields with matching names.
    FullDataMemTable.CopyDataSet(PartialData);
  until PartialData.IsEmpty;

2)如果你想在内存中一次只有一组数据,你可以将DataSet包装在另一个复制某些调用的对象中(Eof,FieldByName,Next等)当“Next”命中时,你会尝试获得更多数据.这里的示例是一个独立的类,但您也可以在DataModule上创建这些公共方法.然后你可以调用dm1.Next而不是像dm1.ds_Generic.DataSet.Next这样的东西.

constructor TDataFetcher.Create(BaseUrl,Resource,Suffix: string);
begin
  FBaseUrl := BaseUrl;
  FResource := Resource;
  FSuffix := Suffix;
end;

procedure TDataFetcher.Open;
begin
  FData := genericREST_Get(FBaseURL,FResource,FSuffix);
end;

procedure TDataFetcher.GetNextData;
begin
  FData := genericREST_Get(FBaseURL,FSuffix);
end;

function TDataFetcher.Eof: boolean;
begin
  result := FData.Eof;
end;

function TDataFetcher.FieldByName(FieldName: string): TField;
begin
  result := FData.FieldByName(FieldName);
end;

procedure TDataFetcher.Next;
begin
  FData.Next;
  if FData.Eof then
  begin
    GetNextData;
  end;
end;

其他选择:
a)从TClientDataSet继承
您还可以通过从TClientDataSet派生新类并重写MoveBy来实现此目的:

function MoveBy(Distance: Integer): Integer; virtual;

如果Inherited MoveBy设置EOF,则可以加载下一组数据.但是,如果您尝试此操作,请确保考虑所有用例.例如,如果调用者使用.Last,您希望发生什么?这是包装类具有的一个优点.除了您公开的内容之外,调用者不能执行任何操作.

function TMyDataSet.MoveBy(Distance: Integer): Integer; override;  
begin
  inherited MoveBy
  if self.Eof then
  begin
    FetchMoreData;
  end;
end;

b)FetchOnDemand
ClientDataSet内置了对FetchOnDemand的支持.我不知道它将如何与RestDataAdapter交互.我敢肯定,如果有足够的工作,你可以获得一个返回总记录数的提供者,然后让ClientDataSet根据需要请求更多的记录.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读