天天看點

[轉載紅魚兒]kbmmw 開發點滴:kbmMW資料集流化

kbmMW提供了QueryService,供我們在用戶端象傳統資料庫應用一樣,直接利用ClientQuery做SQL查詢,以及送出,并且能夠在客 戶端以事務的方式送出多個資料集,應該說,QueryService為我們提供了非常好的便利,快速将兩層應用轉為多層應用,如果用過ASTA,就會發 現,QueryService在對兩層應用的轉化上,要比其實作的更完美,層次更清晰。但在實際項目中,如果考慮應用伺服器對多平台的支援以及業務邏輯的 集中實作,那麼僅僅使用QueryService是不夠的,我們可能還要使用WebService等kbmMW提供的其他服務,這時候涉及到一個問題,如 何自己控制資料集的流化,就象QueryService一樣,通過在服務端将一個Query流化,在用戶端将收到的流再調入一個ClientQuery, 反之亦然。

對此,kbmMW為我們同樣提供了完美的機制,以實作用不同的格式的流在伺服器及用戶端間傳遞資料集。來看看伺服器端的實作:

在一個Service中放置一個TkbmMWUNIDACQuery,命名為q,設定好ConnectionPool及SessionName屬性;

再放置需要的kbmMWXXXStreamFormat,然後為Service增加一個方法SUM1,方法的第一個參數,定為用戶端要求傳遞的流格式,至此,可以看下面的實作代碼了。

// Functions published by the service.

//------------------------------------

function TwsYH.PerformSUM1(ClientIdent:TkbmMWClientIdentity; const

Args:array of Variant):Variant;

var

st:TkbmMWMemoryStream;

begin

// Enter code here to perform function SUM1

q.Close;

q.SQL.Add('Select * from T1');

q.Open;

st:=TkbmMWMemoryStream.Create;

case Args[0] of

0:q.SaveToStreamViaFormat(st,kbmMWBinaryStreamFormat1);

1:q.SaveToStreamViaFormat(st,kbmMWJSONStreamFormat1);

2:q.SaveToStreamViaFormat(st,kbmMWXMLStreamFormat1);

end;

    resultStream.LoadFromStream(st);

st.Free;

實作很簡單,設定SQL,執行查詢,按用戶端要求的格式生成Stream,然後寫到ResultStream中。對于用戶端的實作,則正好相反:

procedure TForm6.Button5Click(Sender: TObject);

  sfBin:TkbmMWBinaryStreamFormat;

  sfJSON:TKbmMWJSONStreamFormat;

  sfXML:TkbmMWXMLStreamFormat;

sfBin:=TkbmMWBinaryStreamFormat.Create(Self);

sfJSON:=TKbmMWJSONStreamFormat.Create(Self);

  sfXML:=TkbmMWXMLStreamFormat.Create(Self);

  try

label1.caption:=kbmMWSimpleClient1.Request('HTTPSERVICE','kbmMW_1.0','sum1',[rgSelectStreamFormat.ItemIndex]);

//     

label1.caption:=kbmMWSimpleClient1.Request('QUERYSERVICES','1.0','sum1',[rgSelectStreamFormat.ItemIndex]);

kbmMWClientQuery2.Close;

case rgSelectStreamFormat.ItemIndex of

0:kbmMWClientQuery2.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,sfBin);

1:kbmMWClientQuery2.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,sfJSON);

2:kbmMWClientQuery2.LoadFromStreamViaFormat(kbmMWSimpleClient1.ResultStream,sfXML);

  finally

sfBin.Free;

sfJSON.Free;

sfXML.Free;

  end;

在用戶端,我們用SimpleClient向指定的Service發送請求,并将請求傳回的的ResultStream按請求的格式,調入一個ClientQuery中。

在做上面測試代碼時,遇到一個很奇怪的問題,就是當選擇BinaryStreamFormat時,ClientQuery加載流時出錯,而另外兩種格式正

常。向xalion請教,他的第一判斷,這不是bug,因為kbmMW第一個使用的就是Bin流,為此,我們還特意把流寫成檔案,對比伺服器與用戶端生成

的檔案是否不同,xalion還做了測試,把這個檔案加載到一個ClientQuery中,測試無問題,而在我這裡就是出錯。足足浪費幾個小時的時間,最

終xalion發現在我的代碼裡加上這句,問題得以解決:

kbmMWBinaryStreamFormat1.sfDef:=[sfLoadDef]

找到病因,原因就好查了,原來,當我們自己用流來操作Query時,使用的StreamFormat控件,不能被ClientQuery.TransportStreamFormat屬性引用(還有ClientTransactionResolve),為什麼呢?

procedure

TkbmMWCustomClientCursor.SetTransportStreamFormat(AFormat:TkbmMWCustomStreamFormat);

if AFormat=FTransportStreamFormat then exit;

if AFormat<>nil then

with AFormat do

sfDef:=[];//這裡ClientQuery把使用的StreamFormat的sfDef清空了!

sfDeltas:=[sfSaveDeltas];

sfData:=[sfLoadData];

ClientTransactionResolve也有同樣的代碼,清空使用的StreamFormat的sfDef屬性值。

至此,得到一條經驗:

就是當我們自己流化Query時,不要使用其他Query的TransportStreamFormat屬性引用的StreamFormat!