当前位置:  开发笔记 > 数据库 > 正文

我怎么能在Delphi中这样做?

如何解决《我怎么能在Delphi中这样做?》经验,为你挑选了2个好方法。

我正在将应用程序从BDE转换为ADO.

在BDE下,如果查询是Open并且您调用了"Sql.Clear",它将自动关闭数据集.

但是,在TADOQuery下不是这种情况,它会引发异常"无法对已关闭的数据集执行操作".

我们的许多遗留代码依赖于旧的BDE行为,因此我从代码中获得了大量运行时错误,如下例所示.

我想覆盖我的TADOCustomQuery类的Sql.Clear方法,以便它包含一个".Close"命令.我怎样才能做到这一点?

".Clear"方法位于SQL属性上,类型为TWideStrings.我真正的问题是:如何在TADOQuery的后代上覆盖TWideStrings.Clear方法?

我已经有一个自定义的TADOQuery组件,这个用于SQL属性:

property SQL: TWideStrings read GetSQL write SetSQL;

这里有一些代码来演示我遇到的问题:

procedure TForm1.btnBDEDemoClick(Sender: TObject);
var
  qryBDE: TQuery;
begin
  //Both queries complete with no problem
  qryBDE := TQuery.Create(nil);
  try
    with qryBDE do begin
      DatabaseName := 'Test';  //BDE Alias
      Sql.Clear;
      Sql.Add('SELECT SYSDATE AS CURDAT FROM DUAL');
      Open;
      ShowMessage('the current date is: ' + FieldByName('CURDAT').AsString);

      Sql.Clear;  //<<<<

Kenneth Coch.. 6

这不是BDE本身的特征.如果你看一下Delphi附带的源码,你会发现你描述的行为是在TQuery.SQL的SetQuery方法上实现的:

procedure TQuery.SetQuery(Value: TStrings);
begin
  if SQL.Text <> Value.Text then
  begin
    Disconnect;
    SQL.BeginUpdate;
    try
      SQL.Assign(Value);
    finally
      SQL.EndUpdate;
    end;
  end;
end;

虽然TADOQuery的SetQuery很简单:

procedure TADOQuery.SetSQL(const Value: TWideStrings);
begin
  FSQL.Assign(Value);
end;

为什么Borland/Codegear决定不实施它同样超出了我.在自定义ADOQuery中实现TQuery的SetQuery应该可以为您提供所需的行为.



1> Kenneth Coch..:

这不是BDE本身的特征.如果你看一下Delphi附带的源码,你会发现你描述的行为是在TQuery.SQL的SetQuery方法上实现的:

procedure TQuery.SetQuery(Value: TStrings);
begin
  if SQL.Text <> Value.Text then
  begin
    Disconnect;
    SQL.BeginUpdate;
    try
      SQL.Assign(Value);
    finally
      SQL.EndUpdate;
    end;
  end;
end;

虽然TADOQuery的SetQuery很简单:

procedure TADOQuery.SetSQL(const Value: TWideStrings);
begin
  FSQL.Assign(Value);
end;

为什么Borland/Codegear决定不实施它同样超出了我.在自定义ADOQuery中实现TQuery的SetQuery应该可以为您提供所需的行为.



2> skamradt..:

问题是当您发出clear时数据集是打开的.对于ADODataset,该属性连接到更新基础ADO数据集,当它随数据集打开而更改时,将引发异常.

所有你需要做的就是在清除之前将数据集关闭,它将全部正常运行.

with qryADO do 
  begin      
    Connection := adoConn;      
    Sql.Clear;      
    Sql.Add('SELECT SYSDATE AS CURDAT FROM DUAL');      
    Open;      
    ShowMessage('the current date is: ' + FieldByName('CURDAT').AsString);
    qryADO.close; // <=== line added to close the database first.
    Sql.Clear;     
    Sql.Add('SELECT SYSDATE-1 AS YESDAT FROM DUAL');      
    Open;      
    ShowMessage('And yesterday was: ' + FieldByName('YESDAT').AsString);    
  end;  //with qryADO

编辑 作为替代方法,您可以创建一个名为SQLCLEAR的新表单方法,如下所示:

function TYourFormOrDataModule.SqlClear;
begin
  qryAdo.Close;
  qryAdo.Sql.Clear;
  qryBde.Sql.Clear;
end;

然后搜索并将"SQL.Clear"替换为"SqlClear".但我更喜欢在原始答案中执行关闭的方法,因为它更加一致,并且更容易长期维护.使用像gExperts这样的工具来查找Sql.Clear的所有实例,并在它变得微不足道之前插入一个qryAdo.Close ......即使有几百个实例.

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有