Delphi - Использование разных TTable и TQuery как одного объекта
Delphi 2010, Win7 - 64
Я пишу приложение, которое включает в себя подключение к различным базам данных. Я использую двух разных поставщиков для доступа к базе данных. Я использую AnyDAC от DA-Soft, который позволяет мне подключаться к "промышленным" базам данных, Oracle, SQL Server и т. Д., И я использую базу данных ComponentAce ABS, которая представляет собой небольшую базу данных SQL на базе ПК. (который я очень рекомендую кстати). Моя проблема заключается в том, что мне нужно написать серию общих процедур, которые могут идти против любых компонентов поставщиков.
Оба компонента имеют компоненты TTable и TQuery. Мне нужно написать набор подпрограмм, некоторые из которых основаны на TTable, а некоторые основаны на TQuery. Эти процедуры могут идти против любых компонентов поставщиков.
Как пример, мне нужно иметь возможность перебирать все строки в таблице TTable. При первом запуске процедуры мне нужно использовать TTable от DA-Soft. В следующий раз, когда я запустил его, мне нужно, чтобы он работал с TTable компонента Ace. Тот же сценарий существует для TQuery.
Мне нужен слой абстракции здесь - по крайней мере, я так думаю. Я не хочу писать каждую процедуру несколько раз. Что было бы рекомендовано для обеспечения этого уровня абстракции / косвенности. Я не слишком обеспокоен стремительной ослепительной скоростью. Имейте в виду - проще, тем лучше, и я НЕ профессиональный программист....
Любые мысли приветствуются. Спасибо всем.
2 ответа
Я предполагаю, что они оба потомки 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
Я предлагаю вам использовать Object Persistence Framework. Я думаю, что Instant Object - это хороший OPF. Теперь я использую это. Благодаря использованию OPF наше приложение будет независимым от СУБД, и нам не нужно создавать подпрограммы для каждой подпрограммы несколько раз.