Delphi Datasnap查询中出错,即使客户端断开连接,仍将连接保留在SQL上
在Delphi Datasnap server中,如果sql查询或存储过程中发生某种错误,sql server将保持连接处于活动状态,即使客户端与Datasnap server断开连接,直到我关闭Datasnap server。 它很容易复制,只需从向导中创建Datasnap服务器。放置一些将返回错误的select查询,例如从用户处选择bud_beer: 还可以从向导创建客户端,将TClientDataSet连接到加载啤酒的提供程序: 现在打开企业管理器,按服务器和用户筛选,并观察连接。 打开ClientDataSet,当然会出现错误。 您将在Enterprise manager中看到该连接。关闭客户端后,连接将保持,并在关闭datasnap服务器时消失。 若打开了更多的客户端,那个么在关闭datasnap服务器之前,SQL server中会有更多的连接中断 来自服务器的源:Delphi Datasnap查询中出错,即使客户端断开连接,仍将连接保留在SQL上,delphi,datasnap,Delphi,Datasnap,在Delphi Datasnap server中,如果sql查询或存储过程中发生某种错误,sql server将保持连接处于活动状态,即使客户端与Datasnap server断开连接,直到我关闭Datasnap server。 它很容易复制,只需从向导中创建Datasnap服务器。放置一些将返回错误的select查询,例如从用户处选择bud_beer: 还可以从向导创建客户端,将TClientDataSet连接到加载啤酒的提供程序: 现在打开企业管理器,按服务器和用户筛选,并观察连接。 打开C
unit ServerContainerUnit1;
interface
uses System.SysUtils, System.Classes,
Datasnap.DSTCPServerTransport,
Datasnap.DSServer, Datasnap.DSCommonServer,
Datasnap.DSAuth, IPPeerServer;
type
TServerContainer1 = class(TDataModule)
DSServer1: TDSServer;
DSTCPServerTransport1: TDSTCPServerTransport;
DSServerClass1: TDSServerClass;
procedure DSServerClass1GetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
procedure DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
procedure DSServer1Disconnect(DSConnectEventObject: TDSConnectEventObject);
private
{ Private declarations }
public
end;
var
ServerContainer1: TServerContainer1;
implementation
uses Winapi.Windows, ServerMethodsUnit1, Unit2;
{$R *.dfm}
procedure TServerContainer1.DSServer1Connect(
DSConnectEventObject: TDSConnectEventObject);
begin
LogInfo('Connected');
end;
procedure TServerContainer1.DSServer1Disconnect(
DSConnectEventObject: TDSConnectEventObject);
begin
LogInfo('Disconnected');
end;
procedure TServerContainer1.DSServerClass1GetClass(
DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
PersistentClass := ServerMethodsUnit1.TServerMethods1;
end;
end.
和dfm:
object ServerContainer1: TServerContainer1
OldCreateOrder = False
Height = 271
Width = 415
object DSServer1: TDSServer
OnConnect = DSServer1Connect
OnDisconnect = DSServer1Disconnect
Left = 96
Top = 11
end
object DSTCPServerTransport1: TDSTCPServerTransport
Server = DSServer1
Filters = <>
Left = 96
Top = 73
end
object DSServerClass1: TDSServerClass
OnGetClass = DSServerClass1GetClass
Server = DSServer1
Left = 200
Top = 11
end
end
object ServerMethods1: TServerMethods1
OldCreateOrder = False
OnCreate = DSServerModuleCreate
OnDestroy = DSServerModuleDestroy
Height = 445
Width = 561
object SQLConnection1: TSQLConnection
DriverName = 'MSSQL'
LoginPrompt = False
Params.Strings = (
'SchemaOverride=%.dbo'
'DriverUnit=Data.DBXMSSQL'
'DriverPackageLoader=TDBXDynalinkDriverLoader,DBXCommonDriver180.' +
'bpl'
'DriverAssemblyLoader=Borland.Data.TDBXDynalinkDriverLoader,Borla' +
'nd.Data.DbxCommonDriver,Version=18.0.0.0,Culture=neutral,PublicK' +
'eyToken=91d62ebb5b0d1b1b'
'MetaDataPackageLoader=TDBXMsSqlMetaDataCommandFactory,DbxMSSQLDr' +
'iver180.bpl'
'MetaDataAssemblyLoader=Borland.Data.TDBXMsSqlMetaDataCommandFact' +
'ory,Borland.Data.DbxMSSQLDriver,Version=18.0.0.0,Culture=neutral' +
',PublicKeyToken=91d62ebb5b0d1b1b'
'GetDriverFunc=getSQLDriverMSSQL'
'LibraryName=dbxmss.dll'
'VendorLib=sqlncli10.dll'
'VendorLibWin64=sqlncli10.dll'
'HostName=xxxx'
'Database=xxxx'
'MaxBlobSize=-1'
'LocaleCode=0000'
'IsolationLevel=ReadCommitted'
'OSAuthentication=False'
'PrepareSQL=True'
'User_Name=xxxxx'
'Password=xxxxx'
'BlobSize=-1'
'ErrorResourceFile='
'OS Authentication=False'
'Prepare SQL=False')
Left = 56
Top = 40
end
object SQLDataSet1: TSQLDataSet
CommandText =
'select bud_beer from users'
MaxBlobSize = -1
Params = <>
SQLConnection = SQLConnection1
Left = 56
Top = 104
end
object DataSetProvider1: TDataSetProvider
DataSet = SQLDataSet1
Left = 140
Top = 104
end
end
和dfm:
object ServerContainer1: TServerContainer1
OldCreateOrder = False
Height = 271
Width = 415
object DSServer1: TDSServer
OnConnect = DSServer1Connect
OnDisconnect = DSServer1Disconnect
Left = 96
Top = 11
end
object DSTCPServerTransport1: TDSTCPServerTransport
Server = DSServer1
Filters = <>
Left = 96
Top = 73
end
object DSServerClass1: TDSServerClass
OnGetClass = DSServerClass1GetClass
Server = DSServer1
Left = 200
Top = 11
end
end
object ServerMethods1: TServerMethods1
OldCreateOrder = False
OnCreate = DSServerModuleCreate
OnDestroy = DSServerModuleDestroy
Height = 445
Width = 561
object SQLConnection1: TSQLConnection
DriverName = 'MSSQL'
LoginPrompt = False
Params.Strings = (
'SchemaOverride=%.dbo'
'DriverUnit=Data.DBXMSSQL'
'DriverPackageLoader=TDBXDynalinkDriverLoader,DBXCommonDriver180.' +
'bpl'
'DriverAssemblyLoader=Borland.Data.TDBXDynalinkDriverLoader,Borla' +
'nd.Data.DbxCommonDriver,Version=18.0.0.0,Culture=neutral,PublicK' +
'eyToken=91d62ebb5b0d1b1b'
'MetaDataPackageLoader=TDBXMsSqlMetaDataCommandFactory,DbxMSSQLDr' +
'iver180.bpl'
'MetaDataAssemblyLoader=Borland.Data.TDBXMsSqlMetaDataCommandFact' +
'ory,Borland.Data.DbxMSSQLDriver,Version=18.0.0.0,Culture=neutral' +
',PublicKeyToken=91d62ebb5b0d1b1b'
'GetDriverFunc=getSQLDriverMSSQL'
'LibraryName=dbxmss.dll'
'VendorLib=sqlncli10.dll'
'VendorLibWin64=sqlncli10.dll'
'HostName=xxxx'
'Database=xxxx'
'MaxBlobSize=-1'
'LocaleCode=0000'
'IsolationLevel=ReadCommitted'
'OSAuthentication=False'
'PrepareSQL=True'
'User_Name=xxxxx'
'Password=xxxxx'
'BlobSize=-1'
'ErrorResourceFile='
'OS Authentication=False'
'Prepare SQL=False')
Left = 56
Top = 40
end
object SQLDataSet1: TSQLDataSet
CommandText =
'select bud_beer from users'
MaxBlobSize = -1
Params = <>
SQLConnection = SQLConnection1
Left = 56
Top = 104
end
object DataSetProvider1: TDataSetProvider
DataSet = SQLDataSet1
Left = 140
Top = 104
end
end
客户:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DBXDataSnap, IPPeerClient,
Data.DBXCommon, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids, Data.DB,
Datasnap.DBClient, Datasnap.DSConnect, Data.SqlExpr;
type
TForm1 = class(TForm)
dspcCommon: TDSProviderConnection;
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
Button1: TButton;
SQLConnection1: TSQLConnection;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses proxy;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet1.Active := true;
end;
end.
问题是:为什么会发生这种情况?我怎样才能避免呢?
谢谢大家! 企业管理器是:Microsoft SQL Server Studio保持数据库连接打开通常是一件好事-它将加快响应速度。查询失败后,下一个可以工作。如果您需要不同的管理,您必须在Datasnap服务器级别处理一些错误,客户端几乎不知道背后的数据库服务器,甚至可能根本没有数据库服务器。哇,那么您的意思是Datasnap服务器没有关闭与SQL server实例的连接,因为对它的一个查询,引发异常?@nolaspeaker,是的,没错。如果启动客户端4次,即使关闭客户端,SQL Server上也会出现4个错误和4个连接。连接将保留在服务器上,直到datasnap服务器关闭。这是100%合理的。在您的datasnap客户端通过关闭客户端到的TSQL连接来断开连接之前,datasnap服务器将保持TCP/IP连接及其与数据库的关联连接处于打开状态。为什么它必须做一些你没有要求它做的事情?作为一名开发人员,您的工作就是亲自应对这种情况,并决定您希望服务器/客户机如何工作。如果要在客户端引发异常时断开连接,请在客户端自己捕获它,然后尝试…exception…end并执行TSqlConnection。关闭自己。