2017-10-09 17 views
6

Sử dụng Delphi Seattle. Tôi có một ứng dụng mà làm cho các cuộc gọi REST khác nhau. Một số cuộc gọi này có thể trả về 10-20 hàng qua JSON, trong khi một số khác có thể trả về 30-40 nghìn hàng. Tôi đã đặt máy chủ REST của mình lên để trả về các hàng theo lô 1.000. Khi dữ liệu trở lại khách hàng của tôi, tôi sử dụng RestDataAdapater, DataSource và Tập dữ liệu khách hàng để hiển thị dữ liệu như thể nó là một bảng cục bộ. Phần này dường như hoạt động tốt. Nếu chúng ta đang ở cuối hàng 1000, thì tôi thay đổi URL và yêu cầu hàng loạt 1.000 hàng tiếp theo.Delphi - Cách tạo Cuộc gọi REST Chung

Thách thức của tôi: Tôi muốn tóm tắt điều này để một thói quen có thể xử lý tất cả các tình huống (ít nhất là cho các cuộc gọi GET). Các phần phức tạp là làm cách nào để xử lý dữ liệu nguồn/khách hàng đặt 1.000 vấn đề hàng? Một ví dụ có thể giúp làm rõ ... Tôi muốn có thể thực hiện một cái gì đó như thế này ...

... 
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; 

Làm cách nào để xử lý vượt ngưỡng 1000 hàng? Khi chương trình gọi điện của tôi (hiển thị ở trên) đi từ hàng 1000 đến 1001, API REST cần phải yêu cầu tập hợp 1000 hàng tiếp theo từ máy chủ. Trong khi tôi biết LÀM THẾ NÀO để làm điều đó, tôi không biết LÀM VIỆC. Tôi muốn "có được 1000 hàng tiếp theo" để được trong thói quen chung (aka thói quen genericREST_Get). Tôi không muốn mỗi thói quen gọi điện thoại phải đối phó với điều đó.

Giả sử tất cả các thói quen sẽ CHỈ tiến lên phía trước, không bao giờ lùi.

Trả lời

2

Dưới đây là một vài lựa chọn để bạn có thể xem xét:

1) Chỉ cần nhận được tất cả các dữ liệu
30-40.000 hàng mà không phải là nhiều để giữ trong bộ nhớ đối với hầu hết các ứng dụng. Ngay cả khi bạn cần thực hiện nhiều cuộc gọi còn lại để nhận dữ liệu bạn có thể làm điều đó ở phía trước. Nếu bạn luôn luôn đi để lặp qua tất cả các dữ liệu thời gian sẽ là tương tự nếu bạn nhận được nó lên phía trước hoặc bên trong vòng lặp:

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) Nếu bạn muốn chỉ có một nhóm các dữ liệu tại một thời điểm trong bộ nhớ bạn có thể bọc DataSet trong một đối tượng khác sao chép một số cuộc gọi (Eof, FieldByName, Next, vv) Khi "Next" hits eof sau đó bạn thử và nhận được nhiều dữ liệu hơn. Ví dụ ở đây là một lớp độc lập, nhưng bạn cũng có thể tạo các phương thức công khai này trên DataModule của bạn. Sau đó, thay vì một cái gì đó như dm1.ds_Generic.DataSet.Next bạn chỉ cần gọi 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; 

Tùy chọn khác:
a) Kế thừa từ TClientDataSet Bạn cũng có thể thực hiện điều này bằng cách bắt nguồn một lớp mới từ TClientDataSet và MoveBy trọng:

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

Nếu MoveBy thừa kế bộ EOF sau đó bạn có thể tải bộ dữ liệu tiếp theo. Tuy nhiên nếu bạn thử điều này, hãy chắc chắn rằng bạn xem xét tất cả các trường hợp sử dụng. Ví dụ bạn muốn điều gì xảy ra nếu người gọi sử dụng .Last? Đó là một lợi thế mà lớp wrapper có. Người gọi không thể làm bất cứ điều gì khác hơn những gì bạn vạch trần.

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

b) FetchOnDemand
ClientDataSet đã xây dựng trong hỗ trợ cho FetchOnDemand. Tôi không biết làm thế nào mà sẽ tương tác với RestDataAdapter. Tôi chắc chắn đã cho đủ công việc bạn có thể có được một nhà cung cấp sẽ trả về tổng số bản ghi và sau đó để cho ClientDataSet yêu cầu nhiều bản ghi hơn khi cần thiết.

Các vấn đề liên quan