服務器端進行客戶計數
除了上面的功能外,這個程序還加上了一個在線用戶以及查詢用戶統計的功能。由於這個應用程序執行模式是 Multiple Instance執行模式,所以當某個前台第一次連上線後,應用程序服務器會激活RemoteDataModule的事件程序,而斷線後又會執行OnDestroy事件程序,因此就可以用這兩個事件計算連上服務器的用戶個數。至於Query個數的計算,則由TQuery的OnAfterOpen事件函數判斷。
-----------------------------------------------------------------
Form1部分,主要用於顯示
-----------------------------------------------------------------
首先在form上安放五個Tlabel控件,其中四個放在一個容器Panel1裡兩個計數的label分別取名為ClIEntCount和QueryCount。屬性Capyion=0。注意,下面的程序在Form1所在的單元Unit1中編寫。
在private下聲明兩個變量:
FQueryCount: Integer;
FClIEntCount: Integer;
在public下聲明兩個過程
procedure UpdateClIEntCount(Incr: Integer);
procedure IncQueryCount;
在實現區寫入過程:
procedure Tform1.UpdateClIEntCount(Incr: Integer);
begin
FClientCount := FClIEntCount + Incr;
ClientCount.Caption := IntToStr(FClIEntCount);
end;
procedure Tform1.IncQueryCount;
begin
Inc(FQueryCount);
QueryCount.Caption := IntToStr(FQueryCount);
end;
--------------------------------------------------------
COM部分
--------------------------------------------------------
在PcSQL窗口的兩個事件OnCreate和OnDesticy,建立事件驅動程序:
procedure TPcSQL.RemoteDataModuleCreate(Sender: TObject);
begin
end;
procedure TPcSQL.RemoteDataModuleDestroy(Sender: TObject);
begin
end;
procedure TPcSQ.RemoteDataModuleCreate(Sender: TObject);
begin
// 增加一位前台上線者(調用Form1上的程序)
Form1.UpdateClIEntCount(1);
end;
procedure TPcSQ.RemoteDataModuleDestroy(Sender: TObject);
begin
// 減少一位前台上線者(調用Form1上的程序)
Form1.UpdateClIEntCount(-1);
end;
在Tqurey的事件AfterOpen建立事件驅動程序:
procedure TPcSQL.Query1AfterOpen(DataSet: TDataSet);
begin
end;
procedure TPcSQ.AdHocQueryAfterOpen(DataSet: TDataSet);
begin
// 新打開一個TQuery查詢(調用Form1上的程序)
Form1.IncQueryCount;
end;
保存,編譯,注冊
二、SQL 客戶端程序
1)建立一個普通的工程。
2)放置一個TDCOMConnrction控件(在Datasnap頁),屬性:
在本機注冊時,可直接設置以下屬性:
ServerName:應用程序服務器注冊名(pro1.pc121)
Connected=true 激活
這時你可以看到服務器端的COM 程序被激活了。
如果在網絡上調試,需要給出服務器名:
ComputerName:服務器名(自動給出網上鄰居)
注意:
ServerGUID的GUID值是自動給出的。
3)放置一個TClIEntDataSet控件(在Data Access頁)
屬性:
RemoteServer= DCOMConnrction1
ProviderName:=DataSetProvider1
Active=true (激活後將能正常連接)
4)放置TDataSource,屬性:
Dataset:指向ClIEntDataSet1
安放合適的數據庫綁定控件。放置Demo控件作為SQL 數據輸入用。
procedure TForm1.Button1Click(Sender: TObject);
begin
// 把Memo內用戶輸入的SQL命令,通過IProvide的
// DataRequest方法傳給應用程序服務器。
ClIEntDataSet1.Close;
ClIEntDataSet1.CommandText := Memo1.Lines.Text;
ClIEntDataSet1.Open;
end;
希望用戶直接調用服務器端的別名,可以加入一個ComboBox控件:
form1的Create 事件可以寫成:
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
DBNames: OleVariant;
begin
// 連上應用程序服務器
DCOMConnection1.Connected := True;
// 取得BDE所有設置的數據庫別名數據
DBNames := DCOMConnection1.APPServer.GetDatabaseNames;
// 假如有數據庫別名數據,則將其一個一個地加到ComboBox控件內
if VarIsArray(DBNames) then
for I := 0 to VarArrayHighBound(DBNames, 1) do
ComboBox1.Items.Add(DBNames[I]);
//把默認的數據庫顯示在第一個
ComboBox1.Text:='mymdb';
end;
運行以後可以看到服務器端的所有的別名:
為了用這個別名列表調用其它的數據庫,考慮到有的數據庫需要輸入密碼和用戶名,需要加入一個新的Form。
File->New->other->new-form 這就加入了一個Form2
加入相應的輸入密碼控件。
其中:CheckBox1的屬性 Name=Check ;而兩個Edit控件的Text屬性為空字符串。
Form2的兩個按鈕事件可以寫成:
procedure TForm2.Button1Click(Sender: TObject);
begin
Check.Checked:=True;
close;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
Check.Checked:=False;
close;
end;
然後回到form1。
首先在private 區聲明一個函數InputDialog,用於啟動讓用戶輸入上線數據的Form2。
function InputDialog(var UserName, PassWord:String):Boolean;
然後在實現區寫入該函數的程序:
// 啟動讓用戶輸入上線數據的Form
function TForm1.InputDialog(var UserName, PassWord:String):Boolean;
var ret:Boolean;
begin
ret:=False;
try
Form2:=TForm2.Create(Application);
Form2.ShowModal;
UserName:=Form2.Edit1.Text;
PassWord:=Form2.Edit2.Text;
if Form2.Check.Checked then ret:=True
else ret:=False;
finally
Form2.Free;
Result:=ret;
end;
end;
現在,可以給ComboBox1加入一個雙擊事件:
procedure TForm1.ComboBox1DblClick(Sender: TObject);
var
UserName, PassWord: string;
begin
// 當您在ComboBox中選取的數據不是空字符串時
if ComboBox1.Text <> '' then
begin
ClIEntDataSet1.Close;
try
// 先給應用程序服務器傳一次空的UserName及PassWord
// 如果後台數據庫是Paradox或DBase可能就沒問題,
// 可是如果是SQL base的關系型數據庫則會收到exception。
//SetDatabaseNames是服務端的COM 方法
DCOMConnection1.APPServer.SetDatabaseName(ComboBox1.Text,'','');
except
// 由於後台數據庫是SQL base的關系型數據庫,所以您必須
// 通過Form2輸入UserName及PassWord,並且把這些數據
// 通過應用程序服務器提供的SetDatabaseName傳給後台數
// 據庫驗證。
on E: Exception do
if E.Message = 'PassWord Required' then
begin
if InputDialog(UserName, PassWord) then
DCOMConnection1.APPServer.SetDatabaseName(ComboBox1.Text,
UserName, PassWord);
end else raise;
end;
end;
end;
以後就可以利用服務器端的別名列表選擇數據庫了。
雙擊該列表框實際上已經實現了聯接,但是,窗口除關閉掉數據庫顯示以外,並沒有其它的反應,這就是說,這個程序使用上還有若干不方便的地方,最重要的就是當連結上數據庫以後,無法知道表的名字。這樣,也無法方便的構造查詢數據集的SQL語言。