Delphi 在运行时设置 AdoConnection 会导致访问冲突

Delphi setting up AdoConnection in runtime gives access violation

我正在尝试编写一个动态创建 TADOQuery 的函数。使用此函数,我可以在函数的参数中更改其 SQL.Text 属性 。我的函数调用应该如何工作:

procedure TDlgMain.FormCreate(Sender: TObject);
var
  Q: TADOQuery;
begin
  Q := NewQuery('select * from Utenti');
  Q.Open;
end;

这里是函数的代码和访问冲突错误的截图,请问有什么办法可以解决吗?

function NewQuery(Conn: TADOConnection; SQL: String): TADOQuery; overload;
function NewQuery(SQL: String): TADOQuery; overload;


function TDMDB.NewQuery(Conn: TADOConnection; SQL: String): TADOQuery;
begin
  Result := TADOQuery.Create(nil);
  Result.Connection := Conn;
  Result.SQL.Text := SQL;
end;

function TDMDB.NewQuery(SQL: String): TADOQuery;
begin
  Result := NewQuery(DBConn, SQL);
end;

该错误表明在您尝试使用它通过 DMDB.NewQuery() 创建查询时尚未创建 TDataModule

错误的原因是两折。

首先,在使用IDE时首先创建一个表单(在你的例子中是DlgMain: TDlgMain),然后是一个数据模块(TDMDB: TDataModule)。这将在项目文件 (.dpr) 中创建表单后创建模块,如下所示:(查看 .dpr 文件,select 菜单 Project - View source

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TDlgMain, DlgMain);
  Application.CreateForm(TDMDB, DMDB);
  Application.Run;
end.

其次,当您尝试在主窗体中创建连接时 OnCreate() 事件,当数据模块尚未创建时,结果就是您看到的 AV。

您可以通过在创建主窗体之前移动数据模块的创建来更正错误:

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TDMDB, DMDB);    // Create this before the form
  Application.CreateForm(TDlgMain, DlgMain);
  Application.Run;
end.

边注,以防你想知道:

您可能知道,通过 Application.CreateForm() 创建的第一个表单成为主表单,并且仍然有效。数据模块不是表单,因此您的 DlgMain 仍然是第一个创建的表单并成为主表单。