国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

多層數據庫開發四:BDE會話期

2019-11-18 18:11:29
字體:
來源:轉載
供稿:網友
   第四章 BDE會話期
  不管是單層、兩層還是多層的數據庫應用程序,一般都要用到BDE(BorlandDatabase Engine)。Delphi 4用Tsession來管理BDE會話期對象,用TSessionList來管理和操縱一個應用程序中所有的BDE會話期對象。
  一般來說,并不需要顯式地把TSession構件放到窗體或數據模塊上,因為數據庫應用程序在每次啟動時會自動創建一個默認的BDE會話期對象叫Session。但如果開發的是一個多線程的數據庫應用程序,就要顯式地用到TSession構件,因為幾個線程有可能要同時連接數據庫,應當避免每次連接數據庫時都要創建應用程序的另一個實例。
4.1 TSession
  TSession構件能夠對一個應用程序內的一組TDatabase構件提供全局控制。當創建數據庫應用程序(包括應用服務器)時,應用程序會自動創建一個默認的BDE會話期對象叫Session。在應用程序中加入新的TDatabase構件和新的數據集構件時,這些構件會自動地處于默認的BDE會話期對象即Session的控制之下。此外,BDE會話期對象還能夠提供訪問Paradox表的口令,指定網絡控制文件所在的目錄,控制數據庫的連接。
  除了默認的BDE會話期對象外,有些應用程序需要用到另外的TSession構件。例如,如果應用程序要并行查詢同一個數據庫,此時,每一個查詢都必須有單獨的BDE會話期。多線程的數據庫應用程序也需要有多個BDE會話期。
  您既可以在設計期加入TSession構件,也可以在運行期動態地創建TSession構件。
4.1.1 默認的BDE會話期對象
  所有的數據庫應用程序都會自動包含一個默認的BDE會話期對象叫Session,它的SessionName屬性是Default。默認的BDE會話期對象能夠對所有的TDatabase構件提供全局控制,不管這些TDatabase構件是在設計期顯式地加到窗體或數據模塊上的還是在運行期動態創建的。注意:默認的BDE會話期對象在設計期是不存在的,它只存在于運行期。
  無論是在設計期還是在運行期加入TDatabase構件時,加入的TDatabase構件都會自動處于默認的BDE會話期對象管理之下。當然,如果您顯式地使用了多個TSession構件,您也可以設置TDatabase構件的SessionName屬性指定其中一個TSession構件。
  TSession最重要的屬性是KeepConnections,如果這個屬性設為True,即使當前沒有打開數據集,也保持與數據庫的連接。這樣,下次打開數據集時,就不必再登錄數據庫。
  注意:應用程序千萬不要試圖刪除默認的BDE會話期對象。
4.1.2 創建另外的BDE會話期對象
  有些情況下需要用到另外的BDE會話期對象。在設計期,您可以把一個或多個TSession構件加到窗體或數據模塊上,然后在對象觀察器中設置它們的屬性,建立事件句柄,調用它們的方法。您也可以在運行期動態地創建BDE會話期對象。
  要在運行期動態地創建BDE會話期對象,可以參照下列步驟:
  第一步是聲明一個TSession類型的變量。
  第二步是調用TSession的Create創建一個TSession的對象實例。Create會自動把Databases數組清為空,把KeepConnections屬性設為True,同時還把新創建的BDE會話期對象加到由Sessions管理的BDE會話期對象的列表中。
  第三步是設置SessionName屬性指定此BDE會話期對象的名稱,注意不能與其他BDE會話期名稱相同。TDatabase和數據集構件都是通過名稱來區分BDE會話期對象。
  第四步是激活此BDE會話期對象,然后設置有關屬性。
  下面的程序示例創建了一個BDE會話期對象,最后又刪掉了這個BDE會話期對象。
var SecondSession: TSession;
Begin
SecondSession := TSession.Create;
With SecondSession Do
Try
SessionName := 'SecondSession';
KeepConnections := False;
Open;
...
Finally
SecondSession.Free;
End;
End;
  實際上,也可以調用TSessionList的OpenSession函數來創建BDE會話期對象,這個函數需要傳遞一個SessionName參數,指定要創建的BDE會話期對象的名稱。如果與SessionName參數匹配的BDE會話期對象已存在,這個函數就激活它。程序示例如下:
Var MySession : TSession;
MySession := Sessions.OpenSession('MySession');
...
MySession.Free;
4.1.3 給BDE會話期對象命名
  TSession的SessionName屬性用于給BDE會話期對象命名。對于默認的BDE會話期對象來說,它的SessionName屬性是“Default”。
  在同一個應用程序內,BDE會話期對象的名稱不能有重復。如果把TSession的AutoSessionName屬性設為True,Delphi 4將自動為每個BDE會話期對象指定一個相異的名稱,這樣就不用擔心重名。如果AutoSessionName屬性設為False,應用程序就必須設置SessionName屬性給每個BDE會話期對象指定一個相異的名稱。在AutoSessionName屬性設為True的情況下,不能直接修改SessionName屬性的值。
  不過,使用AutoSessionName屬性有許多限制。例如,如果窗體或數據模塊上有多個TSession構件,就不能把AutoSessionName屬性設為True。如果窗體或數據模塊上已經有一個TSession構件,并且它的AutoSessionName屬性設為True,就不能再把另一個TSession構件加到窗體或數據模塊上。
  TDatabase構件和數據集構件都有一個SessionName屬性,用于指定一個BDE會話期對象的名稱。如果它們的SessionName屬性為空,表示使用默認的BDE會話期對象。
  下面這個例子首先調用TSessionList的OpenSession創建一個BDE會話期對象,然后設置Database1的SessionName屬性指定剛創建的BDE會話期對象。
var
IBSession: TSession;
...
Begin
IBSession := Sessions.OpenSession('InterBaseSession');
Database1.SessionName := 'InterBaseSession';
End;
4.1.4 激活BDE會話期對象
  如果TSession的Active屬性返回True,表示BDE會話期對象處于活動狀態。如果把這個屬性設為True,將激活BDE會話期對象,并觸發OnStartup事件。
  激活了BDE會話期對象后,就可以調用OpenDatabase函數來連接數據庫。
  把Active屬性設為True,相當于調用Open。把Active屬性設為False,相當于調用Close。
  對于默認的BDE會話期對象即Session,最好不要把它的Active屬性設為False。
  當BDE會話期對象被激活時將觸發OnStartup事件,這樣就有機會設置NetFileDir、PRivateDir和ConfigMode等屬性,不過,NetFileDir和PrivateDir屬性只在訪問Paradox表才是有效的。ConfigMode屬性用于設置哪些BDE別名是可見的。
4.1.5 KeepConnections屬性
  如果KeepConnections屬性設為True,即使當前沒有打開任何數據集,也保持與數據庫的連接。如果這個屬性設為False,當所有的數據集都關閉時,就斷開與數據庫的連接。
  這個屬性是針對動態生成的臨時的TDatabase構件而言的,如果顯式地使用了TDatabase構件,將以它的KeepConnections屬性為準。
  如果一個應用程序需要頻繁地打開和關閉所有的數據集,特別是當這些數據集是在一個遠程數服務器上時,最好把KeepConnections屬性設為True,這樣可以避免再次登錄到遠程服務器。否則,應用程序不得不重新登錄。
  不過,即使在KeepConnections屬性設為True的情況下,仍然可以調用DropConnections函數把空的連接斷開。所謂空的連接,是指當前并沒有打開任何數據集,但由于KeepConnections屬性設為True,仍然保持在連接狀態。
4.1.6 打開和斷開連接
  要打開一個數據庫的連接,調用OpenDatabase函數。這個函數需要傳遞一個DatabaseName參數,用于指定要打開的數據庫的名稱,可以設為BDE別名或TDatabase構件的名稱。對于Paradox或dBASE,DatabaseName參數也可以設為表所在的路徑。
  下面的程序示例試圖打開別名為DBDEMOS的數據庫:
var
DBDemosDatabase: TDatabase;
Begin
DBDemosDatabase := Session.OpenDatabase('DBDEMOS');
...
End;
  OpenDatabase會首先自動激活BDE會話期(如果還沒有激活的話),然后判斷DatabaseName參數是否與BDE會話期對象所管理的TDatabase構件的名稱匹配,如果沒有找到匹配的數據庫,OpenDatabase就會自動創建一個臨時的TDatabase構件。最后,OpenDatabase調用TDatabase的Open連接數據庫。
  OpenDatabase實際上是使一個內部的計數加1,只要這個計數大于0,數據庫就處于連接狀態。
  可以調用CloseDatabase函數來關閉一個數據庫。與OpenDatabase一樣,CloseDatabase也需要傳遞一個DatabaseName參數來指定要關閉的數據庫,例如:
  Session.CloseDatabase(DBDemosDatabase);
  CloseDatabase實際上是使一個內部的引用計數減1,當引用計數減到0時,數據庫才被關閉。
  如果DatabaseName參數指定的數據庫是由一個臨時的TDatabase構件管理的,而且KeepConnections屬性設為False,當數據庫被關閉的同時,相應的TDatabase構件也被刪除。
  在KeepConnections屬性設為False的情況下,對于那些臨時創建的TDatabase構件來說,如果當前沒有打開任何數據集,數據庫將自動關閉,TDatabase構件將自動刪除。對于那些顯式加到窗體或數據模塊上的TDatabase構件來說,需要調用Close才能關閉數據庫。
  如果要一次關閉所有的數據庫,可以把BDE會話期對象的Active屬性設為False,或者調用Close函數。把Active屬性設為False,會自動調用Close,而Close會關閉所有的數據庫,刪除所有臨時創建的TDatabase構件,然后依次調用那些顯式使用的TDatabase的Close,最后,把BDE會話期的句柄設為NIL。
  在打開和關閉數據庫之前,可能需要調用FindDatabase函數來查找一個特定的數據庫是否存在。FindDatabase函數需要傳遞一個DatabaseName參數,用于指定要查找的數據庫,可以設為BDE別名或者TDatabase構件的名稱。對于Paradox或dBASE表來說,可以設為表所在的路徑。如果找到的話,FindDatabase函數就返回一個TDatabase構件,否則,就返回NIL。下面這個例子試圖搜索別名為DBDEMOS的數據庫:
var
DB: TDatabase;
Begin
DB := Session.FindDatabase('DBDEMOS');
If (DB = nil) then DB:=Session.OpenDatabase('DBDEMOS');
If Assigned(DB) and DB.Active then
 Begin
  DB.StartTransaction;
  ...
 End;
End;
4.2 檢索有關BDE會話期的信息
  TSession提供了許多方法用于檢索有關BDE會話期的信息如別名的參數等,下面簡單介紹這些方法。
.GetAliasDriverName返回一個別名的驅動程序;
.GetAliasNames返回所有BDE別名的列表;
.GetAliasparams返回一個別名的參數的列表;
.GetConfigParams返回配置文件中的特定信息;
.GetDatabaseNames返回所有BDE別名的列表(含占用的別名);
.GetDriverNames返回已安裝的驅動程序的列表;
.GetDriverParams返回一個驅動程序的參數;
.GetStoredProcNames返回一個數據庫中的存儲過程名;
.GetTableNames返回一個數據庫中的表格名。
  上述方法中,除了GetAliasDriverName返回一個字符串外,其他方法都是返回一個列表。下面的例子試圖檢索所有的BDE別名:
  var List: TStringList;
Begin
List := TStringList.Create;
Try
Session.GetDatabaseNames(List);
...
Finally
List.Free;
End;
End;
4.3 管理BDE別名
  對于BDE會話期對象來說,BDE別名特別重要,許多方法都需要傳遞一個數據庫的別名作為參數。TSession提供了管理BDE別名的功能。
4.3.1 指定別名的可見性
  ConfigMode屬性用于設置哪些BDE別名對BDE會話期是可見的。ConfigMode屬性是一個集合,默認值是[cmAll],相當于[cfmVirtual,cfmPersistent],表示所有的別名對BDE會話期都是可見的,包括BDE配置文件中定義的別名、BDE會話期創建的專用別名。
  使用ConfigMode屬性的主要目的是限制別名的可見性。例如,可以把ConfigMode屬性設為[cfmVirtual],表示只能看到本BDE會話期創建的別名,不能看到其他BDE會話期創建的別名,也不能看到BDE配置文件中定義的永久別名。
  在BDE會話期創建的別名只存在于內存中,默認情況下,只對本BDE會話期是可見的,其他BDE會話期即使是在同一個應用程序內都無法看到這些別名。
  如果要使BDE會話期創建的別名能夠被所有的BDE會話期甚至其他應用程序看到,首先要調用SaveConfigFile把別名保存到BDE配置文件中,這樣,其他BDE會話期或其他應用程序才可以使用這個別名。當然,ConfigMode 屬性需要設為[cmAll]。
4.3.2 創建、修改和刪除別名
  要創建一個SQL服務器的別名,可以調用AddAlias函數。要創建一個本地數據庫如Paradox、dBASE或ASCII文本的別名,可以調用AddStandardAlias函數。
  AddAlias需要傳遞三個參數,其中,Name參數用于指定名稱,Driver參數用于指定SQL Links驅動程序,List參數用于指定連接參數。程序示例如下:
var
AliasParams: TStringList;
Begin
AliasParams := TStringList.Create;
Try
With AliasParams Do
Begin
Add('OPEN MODE=READ');
Add('USER NAME=TOMSTOPPARD');
Add('SERVER NAME=ANIMALS:/CATS/PEDIGREE.GDB');
End;
Session.AddAlias('CATS', 'INTRBASE', AliasParams);
Finally
AliasParams.Free;
End;
End;
  與AddAlias不同的是,AddStandardAlias用于為Paradox、dBASE或文本創建別名,不需要連接參數,只需要指定一個路徑和默認的驅動程序。程序示例如下:
  AddStandardAlias('MYDBDEMOS', 'C:/TESTING/DEMOS/', 'Paradox');
  要說明的是,調用AddAlias或AddStandardAlias函數創建的別名只存在于內存中,要把別名永久地保存到BDE配置文件中,請調用SaveConfigFile函數。
  創建了一個別名后,就可以調用ModifyAlias來修改別名的參數。ModifyAlias需要傳遞兩個參數,一個是要修改的別名,還有一個是要修改的參數的列表。
  下面這個例子把CATS別名的OPEN MODE參數設為READ/WRITE:
var
List: TStringList;
Begin
List := TStringList.Create;
With List Do
Begin
Clear;
Add('OPEN MODE=READ/WRITE');
End;
Session.ModifyAlias('CATS', List);List.Free;
...
End;
  雖然CATS別名的參數有幾個,但傳遞給ModifyAlias的列表中只需包含要修改的參數。
  要刪除一個BDE會話期創建的別名,可以調用DeleteAlias函數。DeleteAlias只需要傳遞一個參數,即要刪除的別名。
  注意:調用DeleteAlias函數僅僅是從內存中把一個別名刪掉,如果要刪除的別名已經永久地保存到BDE配置文件中,調用了DeleteAlias函數后還需要調用SaveConfigFile函數。
4.4 遍歷所有的TDatabase構件
  這一節要介紹TSession的兩個屬性:Databases和DatabaseCount,用這兩個屬性可以遍歷由一個BDE會話期對象管理的所有的TDatabase構件。
  Databases屬性是一個數組,它的每一個元素是一個處于活動狀態的TDatabase構件,這些TDatabase構件都處于BDE會話期對象的管理之下。
  DatabaseCount屬性是一個整數,表明Databases數組中元素的個數。隨著數據庫的打開和關閉,DatabaseCount屬性會自動變化。例如,在KeepConnections屬性設為False并且沒有顯式使用TDatabase構件的情況下,每打開一個數據庫,DatabaseCount屬性就會加1,每關閉一個數據庫,DatabaseCount屬性就會減1。
  DatabaseCount屬性一般要與Databases屬性配合使用。例如,下面的代碼把所有TDatabase構件的KeepConnection屬性設為True:
var
MaxDbCount: Integer;
Begin
With Session Do
If (DatabaseCount > 0) then
For MaxDbCount := 0 to (DatabaseCount - 1) Do
Databases[MaxDbCount].KeepConnections:= True;
End;
4.5 訪問Paradox表
  TSession的NetFileDir屬性和PrivateDir屬性只適用于Paradox表。其中,NetFileDir屬性用于指定Paradox網絡控制文件即PDOXUSRS.NET所在的目錄,凡是需要共享Paradox表的應用程序必須指定這個文件所在的目錄。PrivateDir屬性用于指定Paradox表的私有目錄,一些臨時文件就存放在私有目錄中。
  Delphi 4會自動從BDE配置文件中檢索網絡控制文件的位置,并把它賦給NetFileDir屬性。也可以設置這個屬性,指定另一個合法的網絡路徑。程序示例如下:
  Session.NetFileDir := ExtractFilePath(application.EXEName);
  注意:只能在當前還沒有打開任何Paradox表的情況下修改NetFileDir屬性。
  如果PrivateDir屬性為空,BDE會自動把當前目錄作為私有目錄。如果要運行的應用程序在一個遠程的文件服務器上,為了避免老是讀寫文件服務器從而影響速度,最好把PrivateDir屬性設為本地的某一個驅動器。
  注意:不能在設計期設置PrivateDir屬性,否則,會出現“Directory Busy”的錯誤。另外,不要把PrivateDir屬性設為一個驅動器的根目錄,最好是子目錄。程序示例如下:
  Session.PrivateDir := 'C:/TEMP';
4.6 口 令
  有的Paradox表和dBASE表是被口令保護的,訪問這些表時需要提供口令。TSession提供了若干個方法和一個事件用于管理口令。
4.6.1 AddPassWord
  TSession的AddPassword函數一般在訪問需要輸入口令的Paradox或dBase表之前調用,用于提供口令。AddPassword唯一的參數就是口令。程序示例如下:
var
Passwrd: String;
Begin
Passwrd := InputBox('Enter password', 'Password:', '');
Session.AddPassword(Passwrd);
Try
 Table1.Open
Except
  ShowMessage('Could not open table!');
Application.Terminate;
End;
End;
  上面這個例子中調用InputBox函數讓用戶輸入口令,也可以調用PasswordDialog函數,或者用TEdit構件做一個編輯框,把PasswordChar屬性設為星號。
  如果用PasswordDialog函數的話,需要傳遞BDE會話期對象作為參數,程序示例如下:
Procedure TForm1.Button1Click(Sender: TObject);
Begin
If PasswordDialog(Session) then
 Table1.Open
Else
 ShowMessage('No password given, could not open table!');
End;
  上述程序將打開一個“Enter password”對話框,如圖4.1所示。
  圖4.1 輸入口令
  對話框上的“Add”按鈕相當于調用AddPassword函數,“Remove”按鈕相當于調用RemovePassword函數,“Remove All”按鈕相當于RemoveAllPasswords函數。
  注意:要在程序中調用PasswordDialog函數,必須引用DBPWDlg單元。
如果您沒有調用AddPassword或PasswordDialog函數來提供口令,當訪問有口令保護的Paradox表和dBase表時,就會自動彈出如圖4.1所示的對話框,讓用戶輸入口令。
4.6.2 RemovePassword和RemoveAllPasswords
  TSession的RemovePassword用于刪除一個先前用AddPassword輸入的口令。RemovePassword只需要傳遞一個參數,即要刪除的口令。程序示例如下:
  Session.RemovePassword('1234');
  TSession的RemoveAllPasswords函數用于刪除先前所有輸入的口令,程序示例如下:
  Session.RemoveAllPasswords;
4.6.3 OnPassword和GetPassword
  當程序試圖打開一個受口令保護的Paradox表時將觸發該事件,應當在處理這個事件的句柄中調用AddPassWord函數輸入一個口令,然后把Continue參數設為True。
  調用GetPassword函數也會觸發OnPassword事件。下面這個例子動態地把一個方法作為處理OnPassword事件的句柄:
Procedure TForm1. FormCreate(Sender: TObject);
Begin
Session.OnPassword := Password;
End;
  Password又調用InputBox函數打開一個輸入框讓用戶輸入口令,如果用戶輸入了口令的話,就把Continue參數設為True。
Procedure TForm1.Password(Sender: TObject;
var Continue: Boolean);
var Passwrd: String;
Begin
Passwrd := InputBox('Enter password', 'Password:', '');
Continue := (Passwrd > '');
Session.AddPassword(Passwrd);
End;
  如果用戶輸入的口令是錯誤的,則仍然不能打開Paradox表,因此,凡是要打開一個Paradox表的代碼必須能處理異常。
  Procedure TForm1.OpenTableBtnClick(Sender: TObject);
const CRLF = #13 + #10;
Begin
Try
Table1.Open; {將觸發OnPassword事件}
Except
On E:Exception Do
Begin
ShowMessage('Error!'+CRLF+E.Message+CRLF);
Application.Terminate;
End;
End;
End;
4.7 管理多個BDE會話期對象
  如果要創建一個多線程的數據庫應用程序,就需要用多個TSession構件,而且必須在設計期顯式地加到窗體或數據模塊上,還要保證它們的SessionName屬性是相異的。
  Delphi 4用TSessionList來管理和操縱一個應用程序中所有的BDE會話期對象,并且已自動聲明了TSessionList的對象示例Sessions。
  如果要動態地創建一個新的BDE會話期對象,這就要用到TSessionList的OpenSession函數。這個函數只需要傳遞一個參數,即要創建的BDE會話期的名稱。程序示例如下:
  Sessions.OpenSession('RunTimeSession' + IntToStr(Sessions.Count + 1));
  上述代碼能保證BDE會話期的名稱不會與已有的BDE會話期重復。
  TSessionList定義了一些屬性和方法用來操縱BDE會話期對象,這里簡單介紹一下:
.Count 返回BDE會話期對象的個數,包括活動的和非活動的;
.FindSession 查找一個指定的BDE會話期對象,如果沒有找到,就返回NIL;
.GetSessionNames 返回所有BDE會話期對象的SessionName屬性組成的列表;
.List 通過這個屬性可以按名稱訪問一個BDE會話期對象;
.OpenSession 動態地創建一個BDE會話期對象;
.Sessions 通過這個屬性可以按序號訪問一個BDE會話期對象。
  在多線程的數據庫應用程序中,在打開一個數據庫之前,首先要檢查這個數據庫是否已經被其他線程打開。怎么檢查呢?用TSessionList的Count屬性和Sessions屬性遍歷所有的BDE會話期對象,逐個檢查每個BDE會話期對象的Databases屬性中是否包含要打開的數據庫,如果有的話,說明這個數據庫已經被某個線程打開,也就是說,不能再在這個BDE會話期內打開數據庫,您得換下一個再進行檢查。
  如果所有的BDE會話期對象都在使用這個數據庫,就必須創建一個新的BDE會話期對象,然后再打開數據庫。

上一篇:多層數據庫開發五:連接數據庫

下一篇:多層數據庫開發二:單層和兩層的應用程序

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 福建省| 马尔康县| 五指山市| 金门县| 腾冲县| 聂拉木县| 宁乡县| 永兴县| 县级市| 古蔺县| 石楼县| 巴楚县| 伽师县| 屏山县| 冷水江市| 延津县| 蓝田县| 留坝县| 乐安县| 板桥市| 调兵山市| 博野县| 嘉兴市| 阆中市| 特克斯县| 济源市| 东方市| 望城县| 修武县| 齐河县| 阿巴嘎旗| 兴和县| 沛县| 克什克腾旗| 高碑店市| 乌拉特中旗| 香港| 湖南省| 武邑县| 搜索| 靖边县|