DBXPool
で を使用DelegateConnection
すると、メソッドを呼び出したときTSQLConnection
に SQLServer が使用できない場合TSQLConnection.Open
、初回はタイムアウトになります。しかし、その後Open
再度呼び出すと、誤動作します。私の本番サービスでは、警告なしでプロセスを強制終了します。例外は発生せず、何も発生しません。プロセスが消えるだけです... テスト用に作成した単純なアプリでは、接続されていない場合でも、接続されDBXPool
ていると見なされます。TSQLConnection
何か提案を提供できるDBXPool
ように、誰かが問題を抱えていましたか?DelegateConnection
ありがとう!
<<< 7/23 編集 #2 >>>
以下の編集 #1 のコードを使用して、DBX フレームワークをトレースしました。次のメソッドは、DBXPool が使用されている場合にのみ呼び出されます。
(ユニット DBXDelegate)
procedure TDBXDelegateConnection.Open;
begin
if not FConnection.IsOpen then
begin
TDBXAccessorConnection(FConnection).Open;
end;
end;
... DBXPool が使用されているかどうかに関係なく呼び出される次のメソッドを呼び出します。
(ユニット DBXCommon)
procedure TDBXConnection.Open;
begin
// mark the state open so memory can be deallocated
// even if derived open or meta query fail
FOpen := true;
DerivedOpen;
DatabaseMetaData;
end;
コメントに注意してください。例外が発生した場合 (たとえば、間違ったユーザー名やタイムアウトなど)、次のコードは DBXPool が使用されていない場合にのみ呼び出されます。
(ユニット DBXCommon)
procedure TDBXConnection.Close;
begin
CloseAllCommands;
RollbackAllTransactions;
DerivedClose;
SetTraceInfoEvent(nil);
FreeAndNil(FDatabaseMetaData);
FOpen := false;
end;
FOpen
DBXPool の使用時に設定が戻されないため、False
次回のDerivedOpen
呼び出し時に実行されるべきではないコードが実行され、AccessViolation とメモリの破損が発生します。RTL がそれをキャッチする場合もあれば、キャッチしない場合もあります (たとえば、本番サービスが Windows によって強制終了されます)。DBXDelegate をさらに深く追跡して、なぜ例外をキャッチせず、TDBXConnection.Close
.
<<< 7/23 編集 #1 >>>
Ken の提案に従って、簡単なサンプル アプリを添付します。私のサービスアプリはただ死んでいます。このアプリは、dbxmss.dll でアクセス違反を示しています (今日)。昨日は、2回目のクリックで例外が発生せず、「接続済み」がTrueとして返されました。私にはメモリの破損のように思えます...
SQLServer を使用する、または使用しないマシンでアプリをビルドして実行します。各ボタンを数回クリックします。どちらも最初のクリックでエラーを返します。「With DBXPool」は、2 回目のクリックで接続されたと認識します。運が良ければAVが見られるかも。「W/O DBXPool」ボタンは毎回失敗しますが、これは正しいことです。
Project1.dpr
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Unit1.dfm
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 301
ClientWidth = 562
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 40
Top = 8
Width = 75
Height = 25
Caption = 'With DBXPool'
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 40
Top = 39
Width = 75
Height = 25
Caption = 'W/O DBXPool'
TabOrder = 1
OnClick = Button2Click
end
object SQLConnection1: TSQLConnection
DriverName = 'MSSQL'
GetDriverFunc = 'getSQLDriverMSSQL'
LibraryName = 'dbxmss.dll'
LoginPrompt = False
Params.Strings = (
'DriverUnit=DBXMSSQL'
'DriverPackageLoader=TDBXDynalinkDriverLoader,DBXCommonDriver150.' +
'bpl'
'DriverAssemblyLoader=Borland.Data.TDBXDynalinkDriverLoader,Borla' +
'nd.Data.DbxCommonDriver,Version=15.0.0.0,Culture=neutral,PublicK' +
'eyToken=91d62ebb5b0d1b1b'
'MetaDataPackageLoader=TDBXMsSqlMetaDataCommandFactory,DbxMSSQLDr' +
'iver150.bpl'
'MetaDataAssemblyLoader=Borland.Data.TDBXMsSqlMetaDataCommandFact' +
'ory,Borland.Data.DbxMSSQLDriver,Version=15.0.0.0,Culture=neutral' +
',PublicKeyToken=91d62ebb5b0d1b1b'
'GetDriverFunc=getSQLDriverMSSQL'
'LibraryName=dbxmss.dll'
'VendorLib=sqlncli10.dll'
'MaxBlobSize=-1'
'OSAuthentication=False'
'PrepareSQL=True'
'ErrorResourceFile='
'drivername=MSSQL'
'schemaoverride=%.dbo'
'HostName=127.0.0.1'
'Database=database'
'User_Name=username'
'Password=password'
'blobsize=-1'
'localecode=0000'
'isolationlevel=ReadCommitted'
'os authentication=False'
'prepare sql=False'
'DelegateConnection=DBXPool'
'DBXPool.MaxConnections=20'
'DBXPool.MinConnections=1'
'DBXPool.ConnectTimeout=1000'
'DBXPool.DriverUnit=DBXPool'
'DBXPool.DelegateDriver=True'
'DBXPool.DBXPool.MaxConnections=20'
'DBXPool.DBXPool.MinConnections=1'
'DBXPool.DBXPool.ConnectTimeout=1000'
'DBXPool.DBXPool.DriverUnit=DBXPool'
'DBXPool.DBXPool.DelegateDriver=True'
'DBXPool.DBXPool.DriverName=DBXPool'
'DBXPool.DriverName=DBXPool')
VendorLib = 'sqlncli10.dll'
Left = 8
Top = 8
end
object SQLConnection2: TSQLConnection
DriverName = 'MSSQL'
GetDriverFunc = 'getSQLDriverMSSQL'
LibraryName = 'dbxmss.dll'
LoginPrompt = False
Params.Strings = (
'DriverUnit=DBXMSSQL'
'DriverPackageLoader=TDBXDynalinkDriverLoader,DBXCommonDriver150.' +
'bpl'
'DriverAssemblyLoader=Borland.Data.TDBXDynalinkDriverLoader,Borla' +
'nd.Data.DbxCommonDriver,Version=15.0.0.0,Culture=neutral,PublicK' +
'eyToken=91d62ebb5b0d1b1b'
'MetaDataPackageLoader=TDBXMsSqlMetaDataCommandFactory,DbxMSSQLDr' +
'iver150.bpl'
'MetaDataAssemblyLoader=Borland.Data.TDBXMsSqlMetaDataCommandFact' +
'ory,Borland.Data.DbxMSSQLDriver,Version=15.0.0.0,Culture=neutral' +
',PublicKeyToken=91d62ebb5b0d1b1b'
'GetDriverFunc=getSQLDriverMSSQL'
'LibraryName=dbxmss.dll'
'VendorLib=sqlncli10.dll'
'MaxBlobSize=-1'
'OSAuthentication=False'
'PrepareSQL=True'
'ErrorResourceFile='
'drivername=MSSQL'
'schemaoverride=%.dbo'
'HostName=127.0.0.1'
'Database=database'
'User_Name=username'
'Password=password'
'blobsize=-1'
'localecode=0000'
'isolationlevel=ReadCommitted'
'os authentication=False'
'prepare sql=False')
VendorLib = 'sqlncli10.dll'
Left = 8
Top = 39
end
end
Unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DBXMSSQL, StdCtrls, DB, SqlExpr, DBXPool;
type
TForm1 = class(TForm)
Button1: TButton;
SQLConnection1: TSQLConnection;
SQLConnection2: TSQLConnection;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
DBXCommon;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
SQLConnection1.Close;
SQLConnection1.Open;
if SQLConnection1.Connected then
MessageDlg('connected connection 1', mtInformation, [mbOK], 0);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
SQLConnection2.Close;
SQLConnection2.Open;
if SQLConnection2.Connected then
MessageDlg('connected connection 2', mtInformation, [mbOK], 0);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
// for testing purposes, shorten the timeout so that the timeout occurs quickly
SQLConnection1.Params.Values[TDBXPropertyNames.ConnectTimeout] := '1';
SQLConnection2.Params.Values[TDBXPropertyNames.ConnectTimeout] := '1';
end;
end.