2014-11-24 49 views
0

所以我有一個ClientDataset(cdsM1)和一個嵌套細節(cdsD1)。我需要在ApplyUpdates之前打印它,所以我克隆它們(cdsMclone和cdsDclone)並過濾主克隆只顯示一個主記錄。如何在ApplyUpdates之前將修改的記錄刷新到CloneSource?

打印後,我需要更新記錄。起初,我想是這樣的:

cdsMclone.Edit; 
cdsMclone.FieldByName('DATEPRINTED').AsString := Now; 
cdsMclone.Post; 
cdsMclone.ApplyUpdates(0); 

但在此之後,如果我改變什麼更多源的ClientDataSet,cdsM1.ApplyUpdates(0)產生衝突(和我的意思一個,你應該在OnReconcileError響應)。但是這個不應該顯示給用戶。另外,使用這種方法,我至少向數據庫發送兩個請求。

一種解決方法是使用CloneSource屬性。例如:

cdsMclone.CloneSource.Edit; 
cdsMclone.CloneSource.FieldByName('DATEWASPRINTED').AsString := Now; 
cdsMclone.CloneSource.Post; 

這樣一來,我可以叫cdsM1.ApplyUpdates(0)無後顧之憂。但我真的不喜歡這樣。似乎代碼正在改變它不應該直接做的事情。此外,如果將來我需要改變嵌套細節中的某些內容,代碼將如何顯示?

還有其他方法可以將克隆的客戶端數據集中的更改返回給源代碼?

回答

0

如果克隆使用CloneCursor()那麼原始和克隆共享相同的基礎數據集創建。它們不是單獨的數據集合,只有兩個不同的視圖到相同的數據。

您不提供用於將原始數據集限制爲1條記錄的過濾器的詳細信息。但是,我懷疑您對記錄的更改與導致您看到的衝突錯誤的過濾條件衝突。

使用克隆避免了這種情況,因爲克隆的數據集沒有應用此過濾器。這是一個單獨的視圖與自己的過濾器。因此沒有衝突。

以這種方式通過克隆遊標修改底層數據集沒有問題。如上所述,克隆和克隆源在相同的數據集上運行,所以這看起來會實現您想要的。

這是你的應用的一個方面,將受益於一些文檔然而,讓意圖和代碼更顯而易見參與對於那些誰維護該代碼在幾個月和幾年來的依賴。

+0

感謝您的回答。我使用'CloneCursor()',你描述的是我期待的。但不是我實現的......呃,過濾器是基於PrimaryKey的。因此,至少在理論上,不應該與任何數據或條件相沖突。就像'cdsMclone.filter:='IDMaster ='+ cdsM1.fieldByName('IDMASTER')。asString;'。由於打印成功,我認爲代碼也可以。 也許我需要創建一個示例代碼來顯示這一點。不幸的是,我只能在明天再次訪問代碼時才能這樣做。 – EMBarbosa 2014-11-24 23:20:41

1

我只有Rave 5 for D7的版本,但以下版本適用於我,無需在主表格,CloneCursor或其他任何類似的過濾器上使用過濾器,只生成主 - 細節報告Master中的當前行。所以,它應該避免你的問題,並避免需要解決。

下面給出的MasterConnFirst和MasterConnValidateRow事件處理程序在Delphi IDE上TRvDataSetConnection用於主設定。

TForm1 = class(TForm) 
[...] 
    cdsMaster: TClientDataSet; 
    cdsDetail: TClientDataSet; 
[...] 
public 
    { Public declarations } 
    Recs : Integer; 
    BM : TBookmark; 
end; 

procedure TForm1.btnReportClick(Sender: TObject); 
begin 
    BM := cdsMaster.GetBookmark; // place a bookmark on the current Master row 
    Recs := 0; // counter for Master records processed by the report 
    RvProject.Execute; 
end; 

procedure TForm1.MasterConnFirst(Connection: TRvCustomConnection); 
begin 
    // The following moves the cdsMaster to its current row, causing the RvReport to skip the 
    // Master rows preceding it. 
    cdsMaster.GotoBookmark(BM); 
    cdsMaster.FreeBookmark(BM); 
end; 

procedure TForm1.MasterConnValidateRow(Connection: TRvCustomConnection; var 
    ValidRow: Boolean); 
begin 
    // This counts the number of Master records processed and returns ValidRow := False 
    // if the Master current row has already been processed. This will cause 
    // Master rows after our current one to be skipped by the RvReport. 

    Inc(Recs); 
    if Recs > 1 then 
    ValidRow := False; 
end; 

無論如何,如果這對你有效,這個答案的其餘部分大部分可能會被刪除,我會在稍後做。

注:

  • 的TRvDataSetConnection還擁有一個帶,根據Rave5開發人員指南,你應該能夠設置爲True一旦目前的主人一個EOF參數的OnEOF事件行已被處理,以使RVReport認爲主控制器沒有更多您感興趣的行。但是,在Rave 5.0.4中,這是D7附帶的版本,即使爲該事件分配處理程序也會導致報告不生成任何內容。大概是Rave 5.0.4中的一個錯誤,並且可能已在更高版本中修復。可惜的是,OnEOF處理程序似乎無法正常工作,因爲使用ValidateRow處理程序似乎效率低下,因爲報告引擎仍需迭代當前主記錄之後的主記錄。

  • 還有的TRvDataSetConnection,DataIndex的兩個屬性,哪些是應該提供告訴它哪些記錄過程的一個更簡單的方法,通過DataIndex設置爲當前記錄的RECNO數據行和數據行到1 DataIndex作品很好,但DataRows設置似乎被忽略,可能是5.0.4中的另一個bug,但也許它在更高版本中正常工作。

+0

我不知道如何僅在Rave Reports中打印當前記錄而不過濾數據集。 – EMBarbosa 2014-11-25 20:06:57

+0

我建議的解決方法工作正常。所以我不認爲需要使用文件創建副本。但我真的不知道只能打印當前記錄而沒有過濾數據集,並且沒有找到幫助。 – EMBarbosa 2014-11-25 20:16:52

+0

那麼,我的更新答案是否有幫助? – MartynA 2014-12-01 20:37:42