Delphi-将不同的TTable和TQuery用作一个对象

Delphi-将不同的TTable和TQuery用作一个对象,delphi,delphi-2010,indirection,tquery,Delphi,Delphi 2010,Indirection,Tquery,Delphi2010,Win7-64 我正在写一个应用程序,它涉及到连接到不同的数据库。我使用两个不同的供应商进行数据库访问。我使用DA Soft的AnyDAC,它允许我连接到“工业”数据库、Oracle、SQL Server等,我使用ComponentAce的ABS数据库,这是一个小型的基于PC的SQL数据库。(顺便说一句,我强烈推荐)。我的问题是,我需要编写一系列通用例程,这些例程可能与任何供应商的组件相冲突 这两个组件都有TTable和TQuery组件。我需要编写一组例程,其中一些是基于T

Delphi2010,Win7-64

我正在写一个应用程序,它涉及到连接到不同的数据库。我使用两个不同的供应商进行数据库访问。我使用DA Soft的AnyDAC,它允许我连接到“工业”数据库、Oracle、SQL Server等,我使用ComponentAce的ABS数据库,这是一个小型的基于PC的SQL数据库。(顺便说一句,我强烈推荐)。我的问题是,我需要编写一系列通用例程,这些例程可能与任何供应商的组件相冲突

这两个组件都有TTable和TQuery组件。我需要编写一组例程,其中一些是基于TTable的,一些是基于TQuery的。这些例程可能与任何供应商的组件相冲突

例如,我需要能够遍历TTable中的所有行。第一次运行例程时,我需要它来使用DA Soft的TTable。下次运行它时,我需要它针对组件Ace的TTable运行它。TQuery也存在同样的情况

我需要一个抽象层——至少我认为我需要。我不想把每一个例程都写多次。建议如何提供这一层的抽象/间接。我并不过分担心速度过快会让人眼花缭乱。请记住-越简单越好,我不是一个专业的程序员

任何想法都值得赞赏。
谢谢大家。

我建议你们使用对象持久性框架。我认为即时对象是很好的OPF。现在我正在使用它。通过使用OPF,我们的应用程序将独立于DBMS,并且我们不需要多次为每个例程创建例程。

我建议您使用对象持久性框架。我认为即时对象是很好的OPF。现在我正在使用它。通过使用OPF,我们的应用程序将独立于DBMS,并且我们不需要多次为每个例程创建例程。

我假设它们都是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

我假设他们都是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

在某种程度上,AnyDAC控件是一种对象持久性框架。它们支持大约15个不同的数据库引擎,但实际上不支持任何本地数据库引擎,这意味着SQL访问,但不必安装本地数据库引擎,这就是为什么我使用组件Ace的ABS数据库。AnyDAC也支持本地数据库:SQLite、Advantage database(dbf)、MS access,AnyDAC控件是一种对象持久性框架。它们支持大约15种不同的数据库引擎,但实际上不支持任何本地数据库引擎,这意味着SQL访问,但不必安装本地数据库引擎,这就是为什么我使用组件Ace的ABS数据库。AnyDAC也支持本地数据库:SQLite,Advantage database(dbf),MS access能否将TTable和TQuery作为它们的共同祖先TDataSet传递?能否将TTable和TQuery作为它们的共同祖先TDataSet传递?