2017-10-09 43 views
6

使用Delphi西雅圖。我有一個應用程序,它可以進行各種REST調用。其中一些調用可能會通過JSON返回10-20行,而其他調用可能會返回30-40行。我已將REST服務器設置爲以1,000個批次返回行。當數據返回到我的客戶端時,我使用RestDataAdapater,DataSource和客戶端數據集來公開數據,就好像它是本地表一樣。這部分似乎工作正常。如果我們在1000行的末尾,則更改URL並請求下一批1,000行。德爾福 - 如何創建一個通用的REST呼叫

我的挑戰:我想抽象這樣一個例程可以處理所有場景(至少對於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例程)中。我不希望每個調用例程都必須處理這個問題。

假設所有的例程只會向前移動,而不會向後移動。

回答

2

這裏有幾個選項供您考慮:

1)剛剛獲得的所有數據
30-40千行是沒有那麼多的內存來存放於大多數應用。即使您需要多次休息呼叫以獲取數據,您也可以預先完成。如果你總是在所有的數據將循環的時間是一樣的,如果你得到它前面或內循環:

repeat 
    PartialData := genericREST_Get(baseURL, resource, 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」碰到eof時,你試着獲取更多的數據。這裏的例子是一個獨立的類,但你也可以在你的DataModule上創建這些公共方法。然後,而不是類似dm1.ds_Generic.DataSet.Next,你只需調用dm1.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, FResource, 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; 

其他選項:
一)繼承的TClientdataSet 您還可以通過獲得來自的TClientdataSet和壓倒一切的MoveBy一個新的類實現這一點:

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

如果繼承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根據需要請求更多的記錄。