2010-03-30 29 views
3

編輯:看起來好像DataSetProvider沒有我需要的這個項目的功能,所以我會實現一個自定義的類來加載數據到ClientDataSet中。DataSetProvider - DataSet到ClientDataSet

我想從一個連接到我的數據庫的TMSQuery中獲取數據,並使用DataSetProvider將一些數據填充到一個ClientDataSet中。

我的問題是,我需要修改這些數據之前,它可以進入我的ClientDataSet。 ClientDataSet具有與原始DB數據不匹配的持久字段。我甚至無法從數據庫獲取字符串到ClientDataSet中的備註字段。

ClientDataSet是我的數據層的一部分,所以我需要將字段中的數據從數據庫符合到ClientDataSet字段(大多數情況下都能夠正確通過,但很多都需要路由和/或轉換)。

有沒有人有這方面的經驗?

回答

0

如果我需要ClientDataSet的數據與數據庫模式不完全匹配,我爲TQuery組件編寫了一個查詢,該查詢以我想要的格式返回數據。然後,我爲TQuery組件編寫自己的單獨的刪除,插入,刷新和更新查詢。

或者,您可以在數據庫上創建視圖並在TQuery組件中使用該視圖。

如果您想要一個獨立於數據庫的自定義ClientDataSet,則需要的是內存數據集。如果您沒有內存數據集組件,Google會將「TClientDataSet作爲內存數據集」。儘管如此,你基本上是一個榮耀的列表視圖組件。當然,您可以掛鉤到內存數據集的OnUpdateRecord中,以瞭解何時更新真實數據集。

2

您正在尋找TDataSetProvider.BeforeUpdateRecord事件。爲此事件編寫一個事件處理程序,您可以手動控制數據如何應用到數據庫。

像這樣的事情

procedure TDataModule1.DataSetProvider1BeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); 
begin 
    { Set applied to tell DataSnap that you have applied this record yourself } 
    Applied := True; 

    case UpdateKind of 
    ukModify: 
     begin 
     Table1.Edit; 
     { set the values of the fields something like this } 
     if not VarIsEmpty(DeltaDS.FieldByName('NewValue')) then 
      Table1['SomeField'] := DeltaDS.FieldByName('SomeField').NewValue; 
     Table1.Post; 
    end; 

    ukInsert: 
     begin 
     Table1.Insert; 
     { set the values of the fields } 
     Table1['SomeField'] := DeltaDS['SomeField'] 
     Table1.Post; 
     end; 

    ukDelete: 
     if Table1.Locate('PrimaryKeyField', DeltaDS['PrimaryKeyField'], []) then 
     Table1.Delete; 
    end; // case 
end; 
+0

+1與kbmMemTable解析器非常相似,恰好相反。 – 2010-03-31 09:08:28

+0

我需要這樣做,但不能直到我能夠將數據導入到ClientDataSet中。我需要能夠對連接到數據庫的DataSet的數據進行相同的修改。可能嗎? – LostNomad311 2010-03-31 14:32:30

+0

這聽起來像是想將來自2個或更多表的數據合併到一個ClientDataSet中,然後將更新應用回源表。如果是這樣的話,我只想在修改我的答案之前進行檢查。 – LachlanG 2010-03-31 19:59:38

0

您可以修改數據通過實施TDataSetProvider.OnGetData事件要ClientDataSet的。

procedure TDataModule1.DataSetProvider1GetData(Sender: TObject; DataSet: TCustomClientDataSet); 
begin 
    DataSet.First; 
    while not DataSet.Eof do begin 
    DataSet.Edit; 
    DataSet['Surname'] := UpperCase(DataSet['Surname']); 
    DataSet.Post; 
    DataSet.Next; 
    end; // while 
end; 

從ClientDataSet應用更新時,可以使用TDataSetProvider.OnUpdateData事件。與OnGetData事件一樣,您正在整個數據集上操作而不是單個記錄。

procedure TDataModule1.DataSetProvider1UpdateData(Sender: TObject; DataSet: TCustomClientDataSet); 
begin 
    DataSet.First; 
    while not DataSet.Eof do begin 
    DataSet.Edit; 
    DataSet['Surname'] := LowerCase(DataSet['Surname']); 
    DataSet.Post; 
    DataSet.Next; 
    end; // while 
end; 

此OnUpdateData事件在OnBeforeUpdateRecord事件之前被調用。此外,OnGetData和OnUpdateData事件在整個數據集上運行,而OnBeforeUpdateRecord對於每個修改的記錄都會調用一次。

+0

我查看了OnGetData事件,但此時數據已經在ClientDataSet中。問題是我的數據類型不匹配,所以TMSQuery中的StringField無法加載到ClientDataSet中的MemoField中,因此我得到一個異常。 – LostNomad311 2010-04-01 14:12:05

+0

你可以在SQL中做所需的轉換,將字符串轉換爲備忘錄等嗎? – LachlanG 2010-04-01 22:48:38

+0

我可以,但這會創建另一個不需要的數據庫訪問點。我正在實現的解決方案是將數據加載到ClientDataSet的自定義類。我很樂意使用這個提供者,但它沒有我需要的功能。 – LostNomad311 2010-04-06 16:43:13