2010-03-30 3 views
3

EDIT: Кажется, что DataSetProvider не имеет необходимых функций для этого проекта, поэтому я буду внедрять пользовательский класс для загрузки данных в ClientDataSet.DataSetProvider - DataSet to ClientDataSet

Я пытаюсь взять данные из TMSQuery, который подключен к моей базе данных, и заполнить ClientDataSet некоторыми из этих данных с помощью DataSetProvider.

Моя проблема в том, что мне нужно будет изменить некоторые из этих данных, прежде чем она сможет войти в мой ClientDataSet. У ClientDataSet есть постоянные поля, которые не совпадают с необработанными данными БД. Я даже не могу получить строку из базы данных в поле memo в 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 в обратном порядке. –

+0

Мне нужно будет это сделать, но только до тех пор, пока я не смогу получить данные в ClientDataSet. Мне нужно иметь возможность делать те же самые изменения в данных, которые выходят из DataSet, подключенного к базе данных. Является ли это возможным? – LostNomad311

+0

Похоже, вы хотите объединить данные из двух или более таблиц в один ClientDataSet, а затем применить обновления к исходным таблицам. Если это так возможно, я просто хочу проверить, прежде чем изменять свой ответ. – LachlanG

0

Вы можете изменить данные, идущие к ClientDataSet, реализовав событие TDataSetProvider.OnGetData.

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 в этот момент. Проблема в том, что мои типы данных не совпадают, поэтому что-то простое, как StringField в TMSQuery, не может загружаться в MemoField в ClientDataSet, поэтому я получаю исключение. – LostNomad311

+0

Можете ли вы сделать преобразования, которые вам нужны в SQL, литье строк в memos и т. Д.? – LachlanG

+0

Я мог бы, но это создало бы другую нежелательную точку доступа БД. Решением, которое я реализую, является пользовательский класс для загрузки данных в ClientDataSet. Я хотел бы использовать этот провайдер, но у него нет необходимых функций. – LostNomad311