konhon

          忘掉過(guò)去,展望未來(lái)。找回自我,超越自我。
          逃避不一定躲的過(guò), 面對(duì)不一定最難過(guò), 孤單不一定不快樂(lè), 得到不一定能長(zhǎng)久, 失去不一定不再擁有, 可能因?yàn)槟硞€(gè)理由而傷心難過(guò), 但我卻能找個(gè)理由讓自己快樂(lè).

          Google

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            203 Posts :: 0 Stories :: 61 Comments :: 0 Trackbacks

          ? 近日(呵呵,這篇文章是去年寫(xiě)的)用了兩個(gè)月開(kāi)發(fā)了一個(gè)物流信息系統(tǒng),這個(gè)系統(tǒng)是兩層、三層相結(jié)合,C/SB/S相結(jié)合的系統(tǒng)。雖然限于時(shí)間的緊張和人手的原因,系統(tǒng)規(guī)模不是很大,但是其中涉及的技術(shù)卻很全面。在這個(gè)《開(kāi)發(fā)技術(shù)篇》中我們將講解我在開(kāi)發(fā)系統(tǒng)中遇到的技術(shù)問(wèn)題及解決方案,希望對(duì)大家有幫助。對(duì)于物流信息系統(tǒng)的分析設(shè)計(jì)問(wèn)題,我將在另一篇文章《物流信息系統(tǒng)開(kāi)發(fā)手記――系統(tǒng)構(gòu)架篇》中講解。

          ?

          一、Midas的安全問(wèn)題。

          ??? Midas技術(shù)是Delphi中進(jìn)行三層開(kāi)發(fā)的首選技術(shù),它不僅有純DCOM/COM+(COM+技術(shù)是.NET技術(shù)的基礎(chǔ))的優(yōu)點(diǎn),而且也結(jié)合了Delphi的快速開(kāi)發(fā)特性,可以快速開(kāi)發(fā)出想要的系統(tǒng),其開(kāi)發(fā)速度是用VC,PB等開(kāi)發(fā)DCOM的數(shù)十倍,把程序員從煩雜的代碼中解脫出來(lái),從而將更多的精力投入到業(yè)務(wù)邏輯的設(shè)計(jì)中去。

          ??? 但是Midas技術(shù)的一個(gè)最令人擔(dān)憂的就是它的安全問(wèn)題:

          遠(yuǎn)端只要知道應(yīng)用服務(wù)器的端口號(hào)即可訪問(wèn)到應(yīng)用服務(wù)器,而一旦訪問(wèn)到應(yīng)用服務(wù)器,TClientDataSet即可獲得ProviderNames列表。一旦知道了ProviderNames列表,這就相當(dāng)于將數(shù)據(jù)庫(kù)暴露在外了。

          關(guān)于可輕易獲得ProviderNames列表的問(wèn)題,我使用下面的方法解決:

          ?在服務(wù)器端定義一個(gè)

          LoginMTS(const AUserId, APassword: WideString): WordBool;

          方法。初始狀態(tài)下,所有的DataSetProvider和數(shù)據(jù)集的連接斷開(kāi)。用戶必須調(diào)用LoginMTS并傳遞用戶名和密碼,登陸成功才將DataSetProvider和數(shù)據(jù)集的連接打開(kāi)。這樣如果用戶驗(yàn)證沒(méi)有通過(guò),即使它獲得了ProviderNames列表也沒(méi)法調(diào)用接口中的方法對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作。

          二、Midas中主從表的實(shí)現(xiàn)

          主從表的應(yīng)用在信息系統(tǒng)中應(yīng)用很廣。在兩層開(kāi)發(fā)中我們可以通過(guò)直接建立兩個(gè)數(shù)據(jù)集之間為主從關(guān)系來(lái)實(shí)現(xiàn)主從表;在三層中雖然我們?nèi)匀豢梢酝ㄟ^(guò)直接建立兩個(gè)數(shù)據(jù)集之間為主從關(guān)系來(lái)實(shí)現(xiàn)主從表,但是這樣就要求把數(shù)據(jù)庫(kù)中所有相關(guān)的數(shù)據(jù)行都下載到本地,喪失了三層開(kāi)發(fā)的優(yōu)勢(shì)。我在實(shí)際中使用下面的方法實(shí)現(xiàn)。這里我以實(shí)現(xiàn)入庫(kù)單查詢、添加、修改、刪除(CRUD)為例來(lái)講解:

          1)新建一個(gè)MTS Data Module,命名為TmtsStockInListBiz,增加如下方法:

          ??? function QueryStockInListMasterById(const AId: WideString;

          ????? var ADatas: OleVariant): WordBool; safecall;

          ??? function QueryStockInListSlaveByMasterId(const AId: WideString;

          ????? var ADatas: OleVariant): WordBool; safecall;

          ??? procedure UpdataStockInListMaster(var ADatas: OleVariant); safecall;

          ??? procedure UpdataStockInListSlave(var ADatas: OleVariant); safecall;

          ??? function GenerateStockInListId: WideString; safecall;

          ?

          QueryStockInListMasterById作用是根據(jù)入庫(kù)單單號(hào)查詢?nèi)霂?kù)單的基本信息(入庫(kù)日期、負(fù)責(zé)人等),Aid為入庫(kù)單單號(hào),Adatas為返回值,其格式就是Midas的數(shù)據(jù)包,可以將其附給ClientDatSetData屬性。

          QueryStockInListSlaveByMasterId作用是根據(jù)入庫(kù)單單號(hào)查詢?nèi)霂?kù)單的詳細(xì)信息(商品條碼,數(shù)量)

          UpdataStockInListMaster是對(duì)入庫(kù)單主表進(jìn)行刪除、添加、修改操作。只要將ClientDataSetDelta屬性做為傳遞即可。

          UpdataStockInListSlave是對(duì)入庫(kù)單從表進(jìn)行刪除、添加、修改操作。

          GenerateStockInListId是產(chǎn)生一個(gè)唯一的入庫(kù)單號(hào)。

          下面是幾個(gè)方法的代碼,都很簡(jiǎn)單,就不多解釋了,可以查看Delphi的幫助。

          function TmtsStockInListBiz.QueryStockInListMasterById(

          ? const AId: WideString; var ADatas: OleVariant): WordBool;

          begin

          ? result := false;

          ? ADatas := null;

          ? try

          ??? cdsQuery.Close;

          ??? cdsQuery.CommandText := 'select * from t_StockInListMaster where Id=:Id';

          ??? cdsQuery.Params.ParamByName('Id').AsString := AId;

          ??? cdsQuery.Open;

          ??? if cdsQuery.RecordCount > 0 then

          ??? begin

          ????? result := true;

          ????? ADatas := cdsQuery.Data;

          ??? end;

          ? finally

          ??? cdsQuery.Close;

          ? end;

          end;

          ?

          procedure TmtsStockInListBiz.UpdataStockInListMaster(

          ? var ADatas: OleVariant);

          var

          ? eCount: Integer;

          ? OwnerData: OleVariant;

          begin

          ? DCOMConStockInList.GetServer.AS_ApplyUpdates('dspStockInListMaster',

          ??? ADatas, -1, eCount, OwnerData);

          end;

          ?

          function TmtsStockInListBiz.GenerateStockInListId: WideString;

          var

          ? LPrior: string;

          ? i: Integer;

          begin

          ? cdsQuery.Close;

          ? cdsQuery.CommandText := 'select top 1 id from t_StockInListMaster order by id desc';

          ? cdsQuery.Open;

          ? LPrior := cdsQuery.FieldByName('Id').AsString;

          ? i := StrToIntDef(RightStr(LPrior,8),0);

          ? Inc(i);

          ? result := 'RK' + FormatFloat('00000000',i);

          ? cdsQuery.Close;

          end;

          ?

          2)、新建一個(gè)應(yīng)用程序,通過(guò)DCOMConnectionSocketConnection等連接到MTS組件,然后就可以調(diào)用MTS的相應(yīng)的方法實(shí)現(xiàn)客戶端功能了。

          放入cdsStockInListMastercdsStockInListSlave兩個(gè)ClientDataSet控件,在控件上點(diǎn)擊右鍵,選擇“FieldsEditor”新建于服務(wù)器中的字段同樣的字段,然后再次在控件上單擊右鍵,選擇“CreateDataSet”,建立一個(gè)本地?cái)?shù)據(jù)庫(kù)。

          3

          根據(jù)入庫(kù)單號(hào)查詢?nèi)霂?kù)單的方法實(shí)現(xiàn):

          procedure TFormStockInList.BtnFindClick(Sender: TObject);

          var

          ? v,vs: OleVariant;

          begin

          ? if SocketConStockInList.AppServer.QueryStockInListMasterById(Trim(LEdtId.Text), v) then

          ? begin

          ??? cdsStockInListMaster.Data := v;//顯示入庫(kù)單主表(主要信息)

          ?

          ??? if SocketConStockInList.AppServer.QueryStockInListSlaveByMasterId(Trim(LEdtId.Text), vs) then

          ????? cdsStockInListSlave.Data := vs; ;//顯示入庫(kù)單從表(明細(xì)信息)

          ? end

          ? else

          ??? ShowMessage('此單不存在!');

          end;

          4)新建入庫(kù)單的實(shí)現(xiàn)

          procedure TFormStockInList.BtnNewClick(Sender: TObject);

          var

          ? LId: string;

          begin

          ? ClearCDSRecord;

          ? cdsStockInListMaster.Open;

          ? cdsStockInListMaster.Insert;

          ? LId := SocketConStockInList.AppServer.GenerateStockInListId;

          ? LEdtId.Text := LId;

          ? cdsStockInListMaster.FieldByName('Id').AsString := LId;

          ? cdsStockInListMaster.FieldByName('GenerateDate').AsDateTime := Now();

          end;

          5)提交功能的實(shí)現(xiàn)

          procedure TFormStockInList.BtnPostClick(Sender: TObject);

          var

          ? LQuerymts: ImtsQueryObjDisp;

          ? LBar: string;

          begin

          ? SetSocketConnectionConnect(SocketConQuery);

          ? LQuerymts := ImtsQueryObjDisp(SocketConQuery.GetServer);

          ?

          ? SocketConQuery.Close;

          ?

          ? if cdsStockInListMaster.RecordCount > 0 then

          ??? SocketConStockInList.AppServer.UpdataStockInListMaster(cdsStockInListMaster.Delta);

          ? if cdsStockInListSlave.RecordCount > 0 then

          ? SocketConStockInList.AppServer.UpdataStockInListSlave(cdsStockInListSlave.Delta);

          end;

          注:本文中ClientDataSet控件的名稱開(kāi)頭一般為cdsTsocketConnection控件的名稱開(kāi)頭一般為SocketCon

          三、動(dòng)態(tài)設(shè)置TsimpleObjectBroker的服務(wù)器列表

          procedure SetSocketConnectionConnect(AValue: TSocketConnection);

          ? procedure FillAppServerList(ABroker: TSimpleObjectBroker);

          ? var

          ??? sl: TStringList;

          ??? i, n: Integer;

          ? begin

          ??? sl := TStringList.Create;

          ??? 從配置文件中讀取服務(wù)器列表,并保存到sl;

          ??? n := sl.Count - 1;

          ??? ABroker.ServerData := null;

          ??? for i := 0 to n do

          ??? begin

          ????? ABroker.Servers.Add;

          ????? ABroker.Servers[i].ComputerName := sl.Strings[i]

          ?? ?end;

          ??? sl.Free;

          ? end;

          var

          ? LBroker: TSimpleObjectBroker;

          begin

          ? LBroker := TSimpleObjectBroker.Create(nil);

          ??? FillAppServerList(LBroker);

          ??? AValue.ObjectBroker := LBroker;

          ??? try

          ????? AValue.Connected := true;

          ??? except

          ????? raise Exception.Create('應(yīng)用服務(wù)器連接錯(cuò)誤!');

          ??? end;

          ??? LBroker.Free;

          end;

          posted on 2007-03-28 05:07 konhon 優(yōu)華 閱讀(2575) 評(píng)論(0)  編輯  收藏 所屬分類: Delphi
          主站蜘蛛池模板: 云林县| 南平市| 商南县| 福海县| 开阳县| 申扎县| 滦南县| 张北县| 大荔县| 广州市| 营口市| 巴林左旗| 额敏县| 宣恩县| 宜丰县| 工布江达县| 安新县| 淮阳县| 旌德县| 孟村| 常州市| 建始县| 榆中县| 榆社县| 临江市| 沙洋县| 武穴市| 金昌市| 营口市| 怀宁县| 松滋市| 来宾市| 名山县| 凯里市| 涪陵区| 恩平市| 讷河市| 阿克| 永兴县| 郧西县| 神池县|