問(wèn)題是這樣開始的:我需要寫一個(gè)COM+,用來(lái)連接不同的數(shù)據(jù)庫(kù)。有的朋友可能會(huì)說(shuō),應(yīng)該為每個(gè)數(shù)據(jù)庫(kù)建立一個(gè)COM+,但是在我的系統(tǒng)里不能這樣。我們?cè)谧鲆粋€(gè)教育輔助系統(tǒng),用戶是學(xué)校(當(dāng)然包括學(xué)校里的老師、學(xué)生、家長(zhǎng)),我們?yōu)槊總€(gè)學(xué)校建一個(gè)數(shù)據(jù)庫(kù),這些數(shù)據(jù)庫(kù)的結(jié)構(gòu)是相同。
當(dāng)然我們還有管理數(shù)據(jù)庫(kù),用于協(xié)調(diào)各數(shù)據(jù)庫(kù)的關(guān)系。每增加一個(gè)學(xué)校用戶,我們就激活一個(gè)新的數(shù)據(jù)庫(kù)給客戶使用,也就是說(shuō),我們的數(shù)據(jù)庫(kù)的個(gè)數(shù)是不斷增加的,而我們的客戶端只有一個(gè),我們不會(huì)為每個(gè)學(xué)校開發(fā)不同的客戶端,我們的COM+也只有一組,而不是為每個(gè)數(shù)據(jù)庫(kù)開發(fā)一組。所以我必須在COM+中根據(jù)用戶的身份讓它去連接不同的數(shù)據(jù)庫(kù)。
很顯然,這個(gè)COM+應(yīng)當(dāng)提供一個(gè)方法,讓其調(diào)用者(可以是客戶端應(yīng)用程序,也可以是其它的中間件)去選擇連接的數(shù)據(jù)庫(kù),在實(shí)際中我們是根據(jù)用戶的ID在管理庫(kù)中查到它的數(shù)據(jù)庫(kù)名,然后連接用戶數(shù)據(jù)庫(kù),在這里,為了簡(jiǎn)化問(wèn)題,我們認(rèn)為調(diào)用者已經(jīng)知道了數(shù)據(jù)庫(kù)的名字,而直接要求調(diào)用這個(gè)數(shù)據(jù)庫(kù)。
在COM+的類中增加一個(gè)私有成員DBName:string,用于保存要連接的數(shù)據(jù)庫(kù)名稱。還應(yīng)該提供這樣一個(gè)方法來(lái)設(shè)置它的值,我開始是這樣寫的
procedure TmtsDBConn.ConnectTo(sDBName:string);
begin
try
DBName:=sDBName;
SetComplete;
Except
SetAbort;
end;
end;
然后在其中放入ADOConnection,ADODataSet,和DataSetProvider控件,分別取名為adoc,adods,dsp。設(shè)置好它們之間的連接關(guān)系,把a(bǔ)doc的連接字符串設(shè)為連接數(shù)據(jù)庫(kù)“DB1”,這是默認(rèn)值,然后在adoc的BeforeConnect事件中:
adoc.ConnectionString:=ConnectStringA+'Initial Catalog='+DBName+';'+ConnectStringC;
這里的ConnectStringA和ConnectStringC是為了動(dòng)態(tài)構(gòu)建連接字符串,預(yù)先設(shè)置好的字符串常量,如下:
const
ConnectStringA='Provider=SQLOLEDB.1;Password=2003;Persist Security Info=True;User ID=sa;';
ConnectStringB='Initial Catalog=DB1;';
ConnectStringC='Data Source=server3;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LXM;Use Encryption for Data=False;Tag with column collation when possible=False';
編譯、安裝這個(gè)COM+。然后編寫客戶端程序調(diào)用它。
在客戶端程序中放一個(gè)DCOMConnection,連接到上面編寫COM+服務(wù)器,再放一個(gè)ClientDataSet,設(shè)置它的RemoteServer和Provider屬性,然后在它的CommandText中寫入SQL語(yǔ)句。然后,放入DataSource控件和DBGrid控件,建立好它們之間的連接關(guān)系。最后放一個(gè)按鈕,在它的Click事件中:
Dcomconnection1.Connected:=true;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active:=true;
Dcomconnection1.Connected:=false;
這段代碼是想測(cè)試一下,能不能訪問(wèn)到DB2數(shù)據(jù)庫(kù)的數(shù)據(jù)??墒墙Y(jié)果是,點(diǎn)下按鈕時(shí),總是報(bào)錯(cuò),這是什么原因呢?
當(dāng)然我們還有管理數(shù)據(jù)庫(kù),用于協(xié)調(diào)各數(shù)據(jù)庫(kù)的關(guān)系。每增加一個(gè)學(xué)校用戶,我們就激活一個(gè)新的數(shù)據(jù)庫(kù)給客戶使用,也就是說(shuō),我們的數(shù)據(jù)庫(kù)的個(gè)數(shù)是不斷增加的,而我們的客戶端只有一個(gè),我們不會(huì)為每個(gè)學(xué)校開發(fā)不同的客戶端,我們的COM+也只有一組,而不是為每個(gè)數(shù)據(jù)庫(kù)開發(fā)一組。所以我必須在COM+中根據(jù)用戶的身份讓它去連接不同的數(shù)據(jù)庫(kù)。
很顯然,這個(gè)COM+應(yīng)當(dāng)提供一個(gè)方法,讓其調(diào)用者(可以是客戶端應(yīng)用程序,也可以是其它的中間件)去選擇連接的數(shù)據(jù)庫(kù),在實(shí)際中我們是根據(jù)用戶的ID在管理庫(kù)中查到它的數(shù)據(jù)庫(kù)名,然后連接用戶數(shù)據(jù)庫(kù),在這里,為了簡(jiǎn)化問(wèn)題,我們認(rèn)為調(diào)用者已經(jīng)知道了數(shù)據(jù)庫(kù)的名字,而直接要求調(diào)用這個(gè)數(shù)據(jù)庫(kù)。
在COM+的類中增加一個(gè)私有成員DBName:string,用于保存要連接的數(shù)據(jù)庫(kù)名稱。還應(yīng)該提供這樣一個(gè)方法來(lái)設(shè)置它的值,我開始是這樣寫的
procedure TmtsDBConn.ConnectTo(sDBName:string);
begin
try
DBName:=sDBName;
SetComplete;
Except
SetAbort;
end;
end;
然后在其中放入ADOConnection,ADODataSet,和DataSetProvider控件,分別取名為adoc,adods,dsp。設(shè)置好它們之間的連接關(guān)系,把a(bǔ)doc的連接字符串設(shè)為連接數(shù)據(jù)庫(kù)“DB1”,這是默認(rèn)值,然后在adoc的BeforeConnect事件中:
adoc.ConnectionString:=ConnectStringA+'Initial Catalog='+DBName+';'+ConnectStringC;
這里的ConnectStringA和ConnectStringC是為了動(dòng)態(tài)構(gòu)建連接字符串,預(yù)先設(shè)置好的字符串常量,如下:
const
ConnectStringA='Provider=SQLOLEDB.1;Password=2003;Persist Security Info=True;User ID=sa;';
ConnectStringB='Initial Catalog=DB1;';
ConnectStringC='Data Source=server3;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LXM;Use Encryption for Data=False;Tag with column collation when possible=False';
編譯、安裝這個(gè)COM+。然后編寫客戶端程序調(diào)用它。
在客戶端程序中放一個(gè)DCOMConnection,連接到上面編寫COM+服務(wù)器,再放一個(gè)ClientDataSet,設(shè)置它的RemoteServer和Provider屬性,然后在它的CommandText中寫入SQL語(yǔ)句。然后,放入DataSource控件和DBGrid控件,建立好它們之間的連接關(guān)系。最后放一個(gè)按鈕,在它的Click事件中:
Dcomconnection1.Connected:=true;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active:=true;
Dcomconnection1.Connected:=false;
這段代碼是想測(cè)試一下,能不能訪問(wèn)到DB2數(shù)據(jù)庫(kù)的數(shù)據(jù)??墒墙Y(jié)果是,點(diǎn)下按鈕時(shí),總是報(bào)錯(cuò),這是什么原因呢?