Delphi - Using different TTable and TQuery as one object

1.6k views Asked by At

Delphi 2010, Win7 - 64

I am writing an app which involves connecting to different databases. I use two different vendors for database access. I use AnyDAC, by DA-Soft, which allows me to connect to "industrial" databases, Oracle, SQL Server, etc, and I use ComponentAce's ABS database, which is a small, PC based SQL database. (which I highly recommend by the way). My issue is that I need to write a series of generic routines which can go against either Vendors components.

Both components have TTable and TQuery components. I need to write a set of routines, some of which are TTable based, and some are TQuery based. These routines can go against either vendors components.

As an example, I need to be able to iterate through all rows in a TTable. The first time I run the routine, I need it to use DA-Soft's TTable. The next time I run it, I need it to run it against Component Ace's TTable. The same scenario exists for TQuery.

I need a layer of abstraction here - at least I think I do. I don't want to have to write every routine multiple times. What would be recommended to provide this layer of abstration / indirection. I am not overly concerned about blinding fast speed. Keep in mind - simpler is better, and I am NOT a professional programmer....

Any thoughts appreciated. Thanks everyone.

2

There are 2 answers

0
Clint Good On BEST ANSWER

I'm assuming they're both TDataSet descendants.

In the simplest case you can just write your routine you just expect a TDataSet parameter. You have access to TDataSet.Next and FieldByName. This would cover quite a number of cases.

If your routine needs to call some code that differs for each TDataSet type then your best bet would be to use interfaces and create a custom descendant of each type

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;

Then you could code your routines just using the IMyDataSetOperations interface

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
2
bagus prasojo On

I suggest u to use Object Persistence Framework. I think Instant Object is good OPF. Now I'm using it. By Using OPF, our application will be DBMS independent, and we needn't create routine for every routine multiple times.