三层中数据库服务器的连接看情况而定,一般情况下是保持连接,用一个adoconnection,里面不是有一项叫keepconnection来着

解决方案 »

  1.   

    引xu_xinyu(雪候鸟)帖子  
      “应该尽量重复使用数据库连接,因为数据库连接是个费时间的事情,这方面的问题非常复杂,你需要多看看李维的书。”   李维的书说得的确是很理想,但有谁真正用他所阐述的方法开发过系统,如果有,效果是不是好呢?再好的思想观点都得经过实践检验是否可行,如果只是他书上那些简单例子来做论据未免站不住脚,何况上面的例子还有很多没有实现,至少我是如此!
        
       一家之言,尽供参考,请大家多发言讨论!
      

  2.   

    adoconnection.keepconnection:=true;
    说实话,我也看过李维的两本书,不过感觉实际上很多照书上做,走不下去。
    其实,很多要靠自己去试。
      

  3.   

    我也看过李维的书, 提供的方法而不是代码,很多事还需要解决KeepConnection 为 true 对你的程序可能没有帮助,你的更新可能代码是在一个数据模块中而每次更新时建立这个模块,唯一的方法是先建立许多模块,用到时取一个空闲的用于更新, 见 TRemoteDataModule 中IAppServer 的定义, 我可以提供一部份关于这种模式的代码(我也刚实现,所以完整代码并不可靠)在你的 RemoteDataModule 中加入重新实现 IAppServer 中所有接口    { IAppServer }
        Function  AS_GetProviderNames: OleVariant;
          Safecall;
        Function  AS_ApplyUpdates(Const ProviderName :WideString; Delta :OleVariant;
          MaxErrors :Integer; Out ErrorCount :Integer; Var OwnerData :OleVariant)
          :OleVariant; Safecall;
        Function  AS_GetRecords(Const ProviderName :WideString; Count :Integer;
          Out RecsOut :Integer; Options :Integer; Const CommandText :WideString;
          Var Params, OwnerData :OleVariant)
          :OleVariant; Safecall;
        Function  AS_DataRequest(Const ProviderName :WideString; Data :OleVariant)
          :OleVariant; Safecall;
        Function  AS_GetParams(Const ProviderName :WideString;
          Var OwnerData :OleVariant)
          :OleVariant; Safecall;
        Function  AS_RowRequest(Const ProviderName :WideString; Row :OleVariant;
          RequestType :Integer; Var OwnerData :OleVariant)
          :OleVariant; Safecall;
        Procedure AS_Execute(Const ProviderName :WideString; Const CommandText
          :WideString; Var Params, OwnerData :OleVariant);
          Safecall;Function TXXXRemoteDataModule.AS_ApplyUpdates(Const ProviderName: WideString;
      Delta: OleVariant; MaxErrors: Integer; Out ErrorCount: Integer;
      Var OwnerData: OleVariant)
      :OleVariant;
    Var
      Provider :TCustomProvider;
    Begin
      Lock;
      Try
        Provider := Providers[ProviderName];
        If Provider.Tag = 0 Then Result := Provider.ApplyUpdates(Delta,
          MaxErrors, ErrorCount, OwnerData)
        Else Begin
          Result := TModuleConnection(Provider.Tag).AS_ApplyUpdates
            (Provider.Name, Delta, MaxErrors, ErrorCount, OwnerData);
        End;
      Finally
        UnLock;
      End;
    End;我利用 CustomProvider (TRemoteDataModule 中定义)中的 Tag, 来存放 TModuleConnection 地址, TModuleConnection 是我写的一个控件, 可以认为是一个 TList 用于存放先分配好的那些 Connection
      

  4.   

    Module Connection 实现//---------------------------------------------------------------------------
      TPooleredConnection = Class;
      TModuleConnection = Class(TComponent)
      Private
        FConnections :TList;
        FCacheCount :Integer;
        FCriticalSection :TCriticalSection;
        FServerName :AnsiString;
        FServerGUID :TGUID;    Procedure SetServerName(Value :AnsiString);
        Procedure SetServerGUID(Value :AnsiString);
        Function  GetServerGUID( ) :AnsiString;
        Procedure SetCacheCount( Value :Integer );
        Function  GetConnectionCount :Integer;
      Protected
        Procedure Loaded; Override;
        Function GetLock( Index :Integer ) :Boolean;
        Function CreateNewConnection( ) :TPooleredConnection;
        Procedure RemoveConnection( Connection :TPooleredConnection );
      Public
        Constructor Create( AOwner :TComponent ); Override;
        Destructor  Free( );
        Function GetConnection( ) :TPooleredConnection;
        Procedure ReleaseConnection(Connection :TPooleredConnection);
        { IAppServer methods }
        Function AS_GetProviderNames: OleVariant;
        Function AS_ApplyUpdates(Const ProviderName :WideString; Delta :OleVariant;
          MaxErrors :Integer; Out ErrorCount :Integer; Var OwnerData :OleVariant)
          :OleVariant;
        Function AS_GetRecords(Const ProviderName :WideString; Count :Integer;
          Out RecsOut :Integer; Options :Integer; Const CommandText :WideString;
          Var Params, OwnerData :OleVariant)
          :OleVariant;
        Function AS_DataRequest(Const ProviderName :WideString; Data :OleVariant)
          :OleVariant;
        Function AS_GetParams( Const ProviderName :WideString;
          Var OwnerData :OleVariant)
          :OleVariant;
        Function AS_RowRequest( Const ProviderName :WideString; Row :OleVariant;
          RequestType :Integer; Var OwnerData :OleVariant)
          :OleVariant;
        Procedure AS_Execute( Const ProviderName :WideString; Const CommandText
          :WideString; Var Params, OwnerData :OleVariant);
      Published
        Property ServerName :AnsiString Read FServerName Write SetServerName;
        Property ServerGUID :AnsiString Read GetServerGUID Write SetServerGUID;
        Property CacheCount :Integer Read FCacheCount Write SetCacheCount Default 10;
        Property ConnectionCount :Integer Read GetConnectionCount;
      End;
    //---------------------------------------------------------------------------
      

  5.   

    //---------------------------------------------------------------------------
    // { DONE -oBin. :TModuleConnection implementation
    //---------------------------------------------------------------------------
    Constructor TModuleConnection.Create( AOwner :TComponent );
    Begin
      Inherited Create( AOwner );  FCacheCount := 10;
      FConnections := TList.Create( );
      FCriticalSection := TCriticalSection.Create( );
    End;
    //---------------------------------------------------------------------------
    Destructor TModuleConnection.Free( );
    Var
      i :Integer;
    Begin
      For i := 0 To FConnections.Count Do
        TPooleredConnection( FConnections[i] ).Free( );
      FConnections.Free( );
      FCriticalSection.Free( );
    End;
    //---------------------------------------------------------------------------
    Procedure TModuleConnection.SetServerName( Value :AnsiString );
    Begin
      If Value <> FServerName Then
      Begin
        If Not ( csLoading In ComponentState ) Then
        Begin
          If CLSIDFromProgID( PWideChar( WideString( Value ) ), FServerGUID )
            <> 0 Then
          Begin
            FillChar( FServerGUID, SizeOf( FServerGUID ), 0 );
            End;
          End;
          FServerName := Value;
      End;
    End;
    //---------------------------------------------------------------------------
    Procedure TModuleConnection.SetServerGUID( Value :AnsiString );
    Var
      ServerName: PWideChar;
    Begin
      If Value = '' Then FillChar( FServerGUID, SizeOf( FServerGUID ), 0 )
      Else Begin
        FServerGUID := StringToGUID( Value );
        If ProgIDFromCLSID( FServerGUID, ServerName ) = 0 Then
        Begin
          FServerName := ServerName;
          CoTaskMemFree(ServerName);
        End;
      End;
    End;
    //---------------------------------------------------------------------------
    Procedure TModuleConnection.SetCacheCount( Value :Integer );
    Begin
      FCacheCount := Value;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.GetConnectionCount :Integer;
    Begin
      Result := FConnections.Count;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.GetServerGUID( ) :AnsiString;
    Begin
      If ( FServerGUID.D1 <> 0 ) Or
        ( FServerGUID.D2 <> 0 ) Or
        ( FServerGUID.D3 <> 0 ) Then
      Begin
        Result := GUIDToString( FServerGUID )
      End
      Else Result := '';
    End;
    //---------------------------------------------------------------------------
    Procedure TModuleConnection.Loaded;
    Begin
      Inherited Loaded;  If Not (csDesigning In ComponentState) Then
      Begin
      End;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.GetLock( Index :Integer ) :Boolean;
    Begin
      FCriticalSection.Enter( );
      Try
        Result := Not TPooleredConnection( FConnections[Index] ).InUse;
        If Result Then
          TPooleredConnection( FConnections[Index] ).InUse := True;
      Finally
        FCriticalSection.Leave( );
      End;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.GetConnection( ) :TPooleredConnection;
    Var
      i :Integer;
    Begin
      Result := Nil;
      For i := 0 To FConnections.Count-1 Do
      Begin
        If GetLock( i ) Then
        Begin
          Result := TPooleredConnection( FConnections[i] );
          Exit;
        End;
      End;
      If Result = Nil Then Result := CreateNewConnection;
    End;
    //---------------------------------------------------------------------------
    Procedure TModuleConnection.ReleaseConnection( Connection :TPooleredConnection );
    Begin
      FCriticalSection.Enter;
      Try
        Connection.InUse := False;
        If FConnections.Count > FCacheCount Then
          RemoveConnection( Connection );
      Finally
        FCriticalSection.Leave;
      End;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.CreateNewConnection( ) :TPooleredConnection;
    Begin
      FCriticalSection.Enter( );
      Try
        Result := TPooleredConnection.Create( );
        Result.Connection := CreateComObject( FServerGUID ) As IAppServer;
        FConnections.Add( Result );
      Finally
        FCriticalSection.Leave( );
      End;
    End;
    //---------------------------------------------------------------------------
    Procedure TModuleConnection.RemoveConnection( Connection :TPooleredConnection );
    Var
      Index :Integer;
    Begin
      Index := FConnections.IndexOf( Connection );
      If Index <> -1 Then FConnections.Delete( Index );
      Connection.Free;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.AS_GetProviderNames: OleVariant;
    Var
      Connection :TPooleredConnection;
    Begin
      Connection := GetConnection( );
      Try
        Result := Connection.AppServer.AS_GetProviderNames;
      Finally
        ReleaseConnection( Connection );
      End;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.AS_ApplyUpdates( Const ProviderName :WideString;
      Delta :OleVariant; MaxErrors :Integer; Out ErrorCount :Integer;
      Var OwnerData :OleVariant ) :OleVariant;
    Var
      Connection :TPooleredConnection;
    Begin
      Connection := GetConnection( );
      Try
        Result := Connection.AppServer.AS_ApplyUpdates( ProviderName,
          Delta, MaxErrors, ErrorCount, OwnerData );
      Finally
        ReleaseConnection( Connection );
      End;
    End;
    //---------------------------------------------------------------------------
    Function TModuleConnection.AS_GetRecords( Const ProviderName :WideString;
      Count :Integer; Out RecsOut :Integer; Options :Integer;
      Const CommandText:WideString; Var Params, OwnerData :OleVariant) :OleVariant;
    Var
      Connection :TPooleredConnection;
    Begin
      Connection := GetConnection( );
      Try
        Result := Connection.AppServer.AS_GetRecords( ProviderName,
          Count, RecsOut, Options, CommandText, Params, OwnerData );
      Finally
        ReleaseConnection( Connection );
      End;
    End;