<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    konhon

    忘掉過去,展望未來。找回自我,超越自我。
    逃避不一定躲的過, 面對不一定最難過, 孤單不一定不快樂, 得到不一定能長久, 失去不一定不再擁有, 可能因為某個理由而傷心難過, 但我卻能找個理由讓自己快樂.

    Google

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

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

    ?

    一、Midas的安全問題。

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

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

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

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

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

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

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

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

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

    1)新建一個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ù)入庫單單號查詢?nèi)霂靻蔚幕拘畔ⅲㄈ霂烊掌?、?fù)責(zé)人等),Aid為入庫單單號,Adatas為返回值,其格式就是Midas的數(shù)據(jù)包,可以將其附給ClientDatSetData屬性。

    QueryStockInListSlaveByMasterId作用是根據(jù)入庫單單號查詢?nèi)霂靻蔚脑敿?xì)信息(商品條碼,數(shù)量)

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

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

    GenerateStockInListId是產(chǎ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)、新建一個應(yīng)用程序,通過DCOMConnection、SocketConnection等連接到MTS組件,然后就可以調(diào)用MTS的相應(yīng)的方法實現(xiàn)客戶端功能了。

    放入cdsStockInListMaster、cdsStockInListSlave兩個ClientDataSet控件,在控件上點擊右鍵,選擇“FieldsEditor”新建于服務(wù)器中的字段同樣的字段,然后再次在控件上單擊右鍵,選擇“CreateDataSet”,建立一個本地數(shù)據(jù)庫。

    3

    根據(jù)入庫單號查詢?nèi)霂靻蔚姆椒▽崿F(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;//顯示入庫單主表(主要信息)

    ?

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

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

    ? end

    ? else

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

    end;

    4)新建入庫單的實現(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)提交功能的實現(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控件的名稱開頭一般為cdsTsocketConnection控件的名稱開頭一般為SocketCon

    三、動態(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ù)器連接錯誤!');

    ??? end;

    ??? LBroker.Free;

    end;

    posted on 2007-03-28 05:07 konhon 優(yōu)華 閱讀(2572) 評論(0)  編輯  收藏 所屬分類: Delphi
    主站蜘蛛池模板: 亚洲福利一区二区三区| 亚洲AV无码AV日韩AV网站| 国产免费的野战视频| 亚洲AV成人一区二区三区观看 | 直接进入免费看黄的网站| 久久精品国产亚洲综合色| 91视频国产免费| 亚洲精品国产日韩无码AV永久免费网| 亚洲男人的天堂在线播放| 免费看国产一级片| 18禁无遮挡无码国产免费网站| 黄页网站在线观看免费| 亚洲影视一区二区| 久久亚洲2019中文字幕| 成熟女人特级毛片www免费| A片在线免费观看| 亚洲aⅴ无码专区在线观看春色 | 丁香花免费高清视频完整版| 欧洲乱码伦视频免费国产| 亚洲av永久无码精品三区在线4| 久久精品国产亚洲Aⅴ香蕉| 成人片黄网站A毛片免费| 精品免费视在线观看| 九九九精品视频免费| 久久亚洲国产成人影院| 亚洲AV无码国产精品麻豆天美| 国产在线a不卡免费视频| 免费观看无遮挡www的小视频| 久久精品免费大片国产大片| 亚洲日本VA中文字幕久久道具| 内射干少妇亚洲69XXX| 亚洲一区二区三区偷拍女厕| 日本免费网站观看| 国产福利在线免费| 亚洲高清免费在线观看| a在线观看免费网址大全| xxxxx做受大片视频免费| 精品国产日韩亚洲一区91| 亚洲激情视频图片| 亚洲欧洲春色校园另类小说| 亚洲AV永久纯肉无码精品动漫|