Delphi: как получить доступ к клиентскому набору данных через дельту

Как в TDatasetProvider.OnBeforeUpdateRecord получить доступ к исходному или исходному набору клиентских данных отправленного параметра DeltaDS?

procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
    SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
    var Applied: Boolean);
var
  sourceCDS: TClientDataset;
begin
  sourceCDS := DeltaDS.???;
  ...
end;

Мне нужно получить доступ к некоторым свойствам из соответствующего набора клиентских данных. Настройка - TSQLDataset / TDatasetProvider / TClientDataset.

Изменить: Причина всех этих хлопот в том, что я хотел получить компонент от TDatasetProvider и назначить OnBeforeUpdateRecord по умолчанию.


person JeffP    schedule 08.08.2016    source источник
comment
Вы, кажется, несколько сбиты с толку. SourceDS - это исходный (исходный) набор данных, а DeltaDS содержит изменения, которые произошли в SourceDS.   -  person Ken White    schedule 08.08.2016
comment
Спасибо, Кен, но я не запутался. Я знаю, что такое SourceDS. Я хочу знать, какой набор Clientdataset сгенерировал рассматриваемую DeltaDS.   -  person JeffP    schedule 08.08.2016
comment
Конечно, при проектировании это не проблема, потому что я могу сказать, какой CDS подключен. Но я пытаюсь абстрагироваться от этого процесса.   -  person JeffP    schedule 08.08.2016
comment
Что значит по умолчанию OnBeforeUpdateRecord? Это не событие провайдера OnBeforeUpdateRecord?   -  person Val Marinov    schedule 08.08.2016
comment
@ValMarinov, я хотел получить / унаследовать компонент от TDatasetProvider. Этому компоненту-потомку я назначу OnBeforeUpdateRecord, который всегда будет оцениваться. Внутри этого OnBeforeUpdateRecord я хотел знать набор Clientdataset, который сгенерировал / создал дельту, которая была передана этому событию.   -  person JeffP    schedule 08.08.2016
comment
Я тебе это сказал, но ты не слушаешь. SourceDS - это набор клиентских данных, который сгенерировал DeltaDS. Прочтите мой первый комментарий еще раз.   -  person Ken White    schedule 08.08.2016
comment
Хорошо, Кен. Я вижу достоинства того, что вы говорите. SourceDS - это исходный набор данных, но я уверен, что это НЕ тот набор клиентских данных, который я ищу. Пожалуйста, вернитесь к комментариям для уточнения.   -  person JeffP    schedule 09.08.2016


Ответы (2)


Я думаю SourceDS это то, что ищите.

Параметр Sender определяет поставщика, применяющего обновления.

Параметр SourceDS - это набор данных, из которого были получены данные. Если исходный набор данных отсутствует, это значение равно нулю (Delphi) или NULL (C ++). Исходный набор данных может быть неактивным при возникновении события, поэтому установите для его свойства Active значение true, прежде чем пытаться получить доступ к его данным.

Параметр DeltaDS - это набор данных клиента, содержащий все применяемые обновления. Текущая запись представляет собой обновление, которое будет применено.

Параметр UpdateKind указывает, является ли это обновление изменением существующей записи (ukModify), новой записи для вставки (ukInsert) или существующей записи для удаления (ukDelete).

Параметр Применено определяет, что происходит после выхода из обработчика событий. Если обработчик событий устанавливает для Applied значение true, поставщик игнорирует обновление: он не пытается его применить и не регистрирует ошибку, указывающую, что обновление не было применено. Если обработчик событий оставляет значение Applied как false, поставщик пытается применить обновление после выхода обработчика событий.

Например:

procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
var Applied: Boolean);
begin
  ShowMessage(TClientDataSet(SourceDS).Name); // get source name
  ...
end;

Изменить

or

  procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
var Applied: Boolean);
begin
  if SourceDS.Name = 'Name1'then
    ...do something ...
  if SourceDS.Name = 'Name2'then
    ...do something ... 
end;
person Val Marinov    schedule 08.08.2016
comment
Спасибо, Вэл. Но уверены ли вы, что можете скрыть / транслировать SourceDS как TClientdataset? Потому что в моей настройке SourceDS будет TSQLDataset. В моей настройке (SQLDS = ›Provider =› CDS) я ищу способ ссылки на CDS (источник). Это не проблема при проектировании, но я пытаюсь сделать это во время выполнения, чтобы инкапсулировать. - person JeffP; 08.08.2016
comment
Нет, я не уверен. Но в вашем вопросе и в вашей настройке (SQLDS = ›Provider =› CDS) это TClientDataSet. - person Val Marinov; 08.08.2016
comment
Но вы можете использовать его как есть (TDataSet), если не уверены. - person Val Marinov; 08.08.2016
comment
Нет, Вэл, я не этого хочу. Могу я также отослать вас к моей правке в вопросе и комментариям под ним для возможных разъяснений. - person JeffP; 08.08.2016

Если вы отследите вызов до своего DataSetProvider1BeforeUpdateRecord, вы увидите, что набор данных, переданный в качестве параметра SourceDS, является набором данных Source из UpdateTree, то есть AFAICS, набором данных, для которого установлено свойство DataSet провайдера. Конечно, это не CDS, из которого была получена дельта (в моем тестовом примере это на самом деле TAdoQuery).

Глядя на исходный код в Provider.Pas, я не могу сразу найти способ определить идентичность исходного CDS Delta. Я не думаю, что это особенно удивительно, потому что операция провайдера вызывается CDS, а не наоборот, и все данные, которые требуются провайдеру от CDS, являются его дельтой.

С другой стороны, вполне справедливо предположить, что событие BeforeUpdateRecord было инициировано самым последним, все еще ожидающим, вызовом ApplyUpdates на одном из ваших CDS, поэтому, если вы отметите это в их BeforeApplyUpdates событии (ах) , это, вероятно, скажет вам то, что вы хотите знать. Я ожидал, что это сработает для одноуровневого обновления, но это может быть сложнее, если UpdateTree работает на вложенных CDS.

Если у всех ваших CDS есть отдельные поставщики, но они совместно используют событие BeforeUpdateRecord, вы можете идентифицировать CDS для данного провайдера, используя следующий код:

function TCDSForm.FindCDSForProvider(DataSetProvider: TDataSetProvider):
    TClientDataSet;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to ComponentCount - 1 do begin
    if Components[i] is TClientDataSet then
      if TClientDataSet(Components[i]).ProviderName = DataSetProvider.Name then begin
        Result := TClientDataSet(Components[i]);
        Exit;
      end;
  end;
end;
person MartynA    schedule 08.08.2016
comment
Вероятно, тогда это единственный способ получить доступ к клиентскому набору данных, хотя он и является грубым. Я попробую это сегодня вечером. - person JeffP; 09.08.2016