在Delphi Datasnap服务器中,如果在sql查询或存储过程中发生某种错误,即使客户端与Datasnap服务器断开连接,SQL Server也会保持连接处于活动状态,直到我关闭Datasnap服务器。 它很容易重现,只需从向导创建Datasnap服务器。放一些肯定会返回错误的选择查询,例如。 "从用户中选择bud_beer" :) 从向导创建客户端,TClientDataSet连接到加载啤酒的提供者:) 现在打开企业管理器,按服务器和用户过滤,并观察连接。 打开ClientDataSet,当然会出错。 您将在Enterprise Manager中看到连接。关闭客户端,连接将保持不变,并在关闭datasnap服务器时消失。 如果打开了更多客户端,那么更多连接将停留在SQL Server中,直到datasnap服务器关闭为止。
来自服务器的来源:
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
服务器方法:
unit ServerMethodsUnit1;
interface
uses System.SysUtils, System.Classes, Datasnap.DSServer, Datasnap.DSAuth,
Data.DBXMSSQL, Data.FMTBcd, Data.DB, Data.SqlExpr, Datasnap.Provider;
type
TServerMethods1 = class(TDSServerModule)
SQLConnection1: TSQLConnection;
SQLDataSet1: TSQLDataSet;
DataSetProvider1: TDataSetProvider;
procedure DSServerModuleCreate(Sender: TObject);
procedure DSServerModuleDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
{var
ServerMethods1: TServerMethods1;}
implementation
{%CLASSGROUP 'Vcl.Controls.TControl'}
uses Unit2;
{$R *.dfm}
procedure TServerMethods1.DSServerModuleCreate(Sender: TObject);
begin
LogInfo('Created methods');
end;
procedure TServerMethods1.DSServerModuleDestroy(Sender: TObject);
begin
LogInfo('Destroyed methods');
end;
end.
和dfm:
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
util的
unit Unit2;
interface
procedure LogInfo(line: string);
implementation
uses Unit1, System.SysUtils;
procedure LogInfo(line: string);
begin
Form1.Memo1.Lines.Add(DateTimeToStr(Now)+' '+line);
Form1.Memo1.Lines.Add('');
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.
谢谢!