Delphi - Использование разных TTable и TQuery как одного объекта - PullRequest
1 голос
/ 15 ноября 2011

Delphi 2010, Win7 - 64

Я пишу приложение, которое включает в себя подключение к различным базам данных. Я использую двух разных поставщиков для доступа к базе данных. Я использую AnyDAC от DA-Soft, который позволяет мне подключаться к «промышленным» базам данных, Oracle, SQL Server и т. Д., И я использую базу данных ComponentAce ABS, которая представляет собой небольшую базу данных SQL на базе ПК. (который я очень рекомендую, кстати). Моя проблема заключается в том, что мне нужно написать серию общих процедур, которые могут идти против любых компонентов Vendors.

Оба компонента имеют компоненты TTable и TQuery. Мне нужно написать набор подпрограмм, некоторые из которых основаны на TTable, а некоторые основаны на TQuery. Эти процедуры могут идти против любых компонентов поставщиков.

В качестве примера мне нужно иметь возможность перебирать все строки в таблице TTable. При первом запуске процедуры мне нужно использовать TTable от DA-Soft. В следующий раз, когда я запустил его, мне нужно, чтобы он работал с TTable компонента Ace. Тот же сценарий существует для TQuery.

Мне нужен здесь слой абстракции - по крайней мере, я так думаю. Я не хочу писать каждую процедуру несколько раз. Что бы рекомендовать для обеспечения этого уровня абстракции / косвенности. Я не слишком беспокоюсь о быстрой скорости. Имейте в виду - проще, тем лучше, и я НЕ профессиональный программист ....

Любые мысли приветствуются. Спасибо всем.

Ответы [ 2 ]

10 голосов
/ 15 ноября 2011

Я предполагаю, что они оба являются потомками TDataSet.

В простейшем случае вы можете просто написать свою подпрограмму, вы просто ожидаете параметр TDataSet.У вас есть доступ к TDataSet.Next и FieldByName.Это охватит целый ряд случаев.

Если вашей подпрограмме нужно вызывать некоторый код, который отличается для каждого типа TDataSet, тогда лучше всего было бы использовать интерфейсы и создать собственного потомка каждого типа

IMyDataSetOperations = interface 
  procedure OpenSpecial;
  function GetDataSet: TDataSet;
end;

TMyAnyDacTable = class(TAnyDacTable, IMyDataSetOperations)
  procedure OpenSpecial;
  function GetDataSet: TDataSet;
end;

TMyComponentAceTable = class(TComponentAceTable, IMyDataSetOperations)
  procedure OpenSpecial;
  function GetDataSet: TDataSet;
end;

procedure TMyAnyDacTable.OpenSpecial
begin
  // code specific for AnyDAC dataset
end;

function TMyAnyDacTable.GetDataSet: TDataSet;
begin
  result := self;
end;

Тогда вы можете кодировать свои подпрограммы, просто используя интерфейс IMyDataSetOperations

function CalculateAverage(const AMyDataSet: IMyDataSetOperations): Currency;
var
  total: Currency;
  i: Count;
begin
  AMyDataSet.OpenSpecial;
  i := 0;
  total := 0;
  AMyDataSet.GetDataSet.First;
  while not AMyDataSet.GetDataSet.Eof do
  begin
    total := total + AMyDataSet.GetDataSet.FieldByName('Amount').AsCurrency;
    Inc(i);  
    AMyDataSet.GetDataSet.Next;
  end

  if i > 0 then
    result := total / i
  else
    result := 0;
end
1 голос
/ 15 ноября 2011

Я предлагаю вам использовать Object Persistence Framework.Я считаю Instant Object хорошим OPF.Теперь я использую это.Благодаря использованию OPF наше приложение будет независимым от СУБД, и нам не нужно создавать подпрограммы для каждой подпрограммы несколько раз.

...