程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 動態創建ClientDataSet的表定義

動態創建ClientDataSet的表定義

編輯:Delphi
前言

  很多人都在問,ClIEntDataSet如何才能在不連接數據庫得情況下,用程序創建起來,並打開數據集。

  在研究了一下TClientDataSet數據集後,發現如果要讓ClIEntDataSet打開的話(Open),必須滿足三個條件中的一個:

  1. ProviderName屬性賦值,即有數據源提供者。
  2. Data屬性賦值。即從其它已經打開的數據集中獲得表結構和數據。
  3. FileName賦值,即從本地文件獲取數據和MetaData。

  這三個條件是TClIEntDataSet的Active屬性的幫助中說的。思考一下,第一和第二基本被排除,我如果有了現成的數據集,還要創建干嗎?第三個又不是那麼容易,你哪知道文件的格式是什麼呢?

  那到底該怎麼做呢?

                         失敗的嘗試

  突然想起TClIEntDataSet中支持InternalCalc(內部計算)字段。內部計算字段可以在設計期加進去,或者也可以在運行期動態加入。我們為了方便,就在設計期加入。見下圖:

  

  可以通過雙擊控件(TClientDataSet)進入字段編輯器,然後右鍵選擇“New Field”命令,得到如圖所示的界面。填寫Name,Type和FIEldType。

  記住:FIEldType一定要是“InternalCalc”。如此反復,你可以選擇添加多個字段。

  打開!報錯:“ProviderName”或Data沒有賦值。

  這個方法不正確,既然要Data,我嘗試著,從其它ClIEntDataSet的Data屬性賦值上。得到結果是:自己新建的字段和數據源的字段都顯示。

  我又進行了進一步的嘗試:那就是讓這個有著新建的字段和原有字段的ClientDataSet的Data賦值到另一個新的ClIEntDataSet上,卻發現新建的字段沒有進入。

  總得來說,這次嘗試是失敗的,不過有如下總結:

  1. 光靠新建內部計算字段是不可行的。
  2. 新建的計算字段不可以進入Data屬性而被傳遞給第二個ClIEntDataSet。

                               XML

  又是XML!ClIEntDataSet本就是斷開連接的數據集控件,應此提供了將數據緩存到磁盤的功能SaveToFile(),其詳細聲明如下:

  procedure SaveToFile(const FileName: string = ''; Format: TDataPacketFormat = dfBinary);

  注意到其中的TDataPacketFormat。它是個枚舉類型,全部的枚舉值如下:

  TDataPacketFormat = (dfBinary, dfXML, dfXMLUTF8);

  大家可能注意到了,dfBinary和dfXMLUTF8都不是我們需要關心的,關心一下我們的dfXML格式。這是個讓人興奮的消息。有了XML,我們就可以查看ClIEntDataSet的MetaData的定義,而且更有了修改的可能!

  調用一下SaveToFile功能,注意保存格式為dfXML。打開文件,如下顯示:

  <?XML version="1.0" standalone="yes" ?> 
- <DATAPACKET Version="2.0">
- <METADATA>
- <FIELDS>
-  <FIELD attrname="NormInfoID" fieldtype="i4">
    <PARAM Name="PROVFLAGS" Value="7" Type="i4" Roundtrip="True" /> 
   </FIELD>
   <FIELD attrname="Description" fieldtype="string.uni" WIDTH="160" /> 
   <FIELD attrname="NormInfoVal" fieldtype="string.uni" WIDTH="510" /> 
   <FIELD attrname="NewField" fieldtype="i4" /> 
   <FIELD attrname="Boolean" fieldtype="Boolean" /> 
   <FIELD attrname="Date" fieldtype="date" /> 
   <FIELD attrname="Time" fieldtype="time" /> 
  </FIELDS>
  <PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" /> 
  </METADATA>
  <ROWDATA /> 
  </DATAPACKET>

  看這個全部的,比較混亂,先看一下結構:

  <?XML version="1.0" standalone="yes" ?> 
- <DATAPACKET Version="2.0">
  + <METADATA>
    <ROWDATA /> 
  </DATAPACKET>

  這下比較清楚了:

  整個XML定義為一個DataPacket,DataPacket包括兩個部分:MetaData和RowData。顯然對我們來說,RowData可以忽視,到時候將RowData的節點清空就是。而MetaData呢?

  看看全部的XML格式,可以看出:MetaData包括FIElds和Params。即字段和數據集參數。

字段

  先重點考慮Fields。看一下FIEld節點的定義,大概可以看出一些:

  1. attrname是指FIEldName
  2. fIEldtype是指字段類型
  3. width是需要寬度的字段類型的參數
  4. 如果需要定義字段的屬性,再加上<Param />節點

  下面我們來研究一下字段類型,我想這也是最主要的!其它屬於高級用法。

MSSQL Type fIEldtype WIDHT SUBTYPE DECIMALS READONLY Binary bin.hex 50       Bit boolean         Char string 10 FixedChar     DateTime dateTime         Decimal fixed 18       Float r8         Image bin.hex   Binary     Int i4         Money fixed 19   4   nChar string.uni 20       nText bin.hex   Text     Numeric fixed 18       nVarChar string.uni 100       SmallDateTime dateTime         Real r8         SmallInt i2         SmallMoney fixed 10   4   Text bin.hex   Text     TimeStamp bin.hex 8     true tinyInt i2         UniqueIdentifIEr string 38 Guid     VarBinary bin.hex 50 Binary     VarChar string 50      

  見上表,這是我在SQLServer2000中,將所有類型的字段都用上,然後在ClientDataSet中得到的,類型對應關系。注意到有SubType屬性,來幫助決定類型。其中沒有值的單元格,表示該屬性沒有用到。寬度值中,除了UniqueIdentifIEr是38外,其余都是采用系統默認寬度。

  分析一下這一張表,可以得到如下一些特點:

  1. 後綴uni表示unicode,沒有後綴,則表示是AnsiCode
  2. 後綴hex表示16進制
  3. i後的數字表示整數所占用的位數,默認為4位
  4. r8表示8位浮點數

                     字段參數

  注意到某些字段的定義下有節點:

<PARAM Name="PROVFLAGS" Value="7" Type="i4" Roundtrip="True" /> 

  先來解釋一下“PROVFLAGS”,在Delphi的源碼裡查找可以發現其實就是對應著TFIEld的屬性ProviderFlags,那麼7也就是好理解的了。

  看TProviderFlag和TProviderFlags的定義

  TProviderFlag = (pfInUpdate, pfInWhere, pfInKey, pfHidden);
  TProviderFlags = set of TProviderFlag;

  既然是集合,那麼7很顯然就是一個集合的整數表示:按順序排的話,7其實就是表示結合[pfInUpdate, pfInWhere, pfInKey]。

  不過不知道為什麼,查看TFIEld的屬性,pfInKey不在集合中。

                                 MetaData屬性

  看看

  <PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" /> 

  可以看出DEFAULT_ORDER和PRIMARY_KEY的意思,但是後面的值呢?研究之後,發現,它是主鍵或索引字段的Index。如果同時兩個字段都是索引,那麼它的格式是:"1 2",中間采用空格隔開。

                            如何使用XML格式?

  好了,格式大概都知道了,現在問題是如何轉載到ClIEntDataSet呢?

  文件是可以,但是顯然不滿足我們當初的需求,在查看一下接口定義,發現除了LoadFromFile還有LoadFromStream。查看一下源碼,其實LoadFromFile就是調用了LoadFromStream。

  好了,只要我們創建了這樣的XML流,就可以動態創建ClIEntDataSet了!

  至於如何創建XML流,不在此討論了

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved