Question

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.

Was it helpful?

Solution

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

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top