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

发布于 2024-12-15 09:30:50 字数 586 浏览 3 评论 0原文

Delphi 2010,Win7 - 64

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

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

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

我在这里需要一个抽象层——至少我认为我需要。我不想多次编写每个例程。建议采取什么措施来提供这一层抽象/间接。我并不太担心令人眼花缭乱的速度。请记住 - 越简单越好,而且我不是专业程序员......

任何想法表示赞赏。 谢谢大家。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凡间太子 2024-12-22 09:30:50

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

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
萌逼全场 2024-12-22 09:30:50

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文