国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

有關TDataSet的研究

2019-11-18 18:36:43
字體:
來源:轉載
供稿:網友
有關TDataSet的研究
   
VCL 的數據庫框架中有一個很重要的抽象類叫TDataSet ,它可以處理非BDE 的數據源。
 
鑒于Delphi的很多數據庫感知控件都是以TDataSet作為接口和數據庫連接的,為了重復使用Delphi現有的資源,已經使我們的小型數據庫能更加健壯,更加可移植,已經提出公共接口,針對接口編程,因此決定將原來的GPF控件改寫由TDataSet繼承。
 
TDataSet本身自己已經封裝了記錄緩沖系統。Buffers就是記錄它的記錄緩沖區的。BufferCount記錄可是用緩沖區的個數。但是Buffers的個數比BufferCount多一個。這多出來的一個是TDataSet用來作為臨時緩沖區的,即TempBuffer。雖然TDataSet已經封裝了,但是對緩沖區的所有實現還得在派生類里實現。但所有在外面可以實現的都是對單個記錄緩沖區的。如:為記錄緩沖區申請空間,釋放空間,初始化緩沖區,以及一些和緩沖區有關的操作。這些在《Delphi 5 開發人員指南》中30章第四節“擴展TDataSet中已經有了很好的說明。

記錄緩沖列表
臨時緩沖區
   

0
1
2
3
.
.
.
最后
臨時
          
           圖1:記錄緩沖列表結構
 
由于TDataSet是個抽象類,所以必須在派生類中實現所有的抽象方法。實現這些抽象方法也正是實現我們的GPF(現改名為GDB)。因為正是這些抽象方法實現了DataSet和數據庫數據的連接。最基本的就是InternalOpen和InternalClose兩個方法。另外要實現使用Field,就得實現GetFieldData,SetFieldData。這里有一點要說明的是在Fields中的Field的順序(即用Fields[I]訪問的順序)和數據庫中字段的循序是不一樣的。我在這里就曾經犯過錯誤。我的解決方法是使用Field中的屬性FieldNo,這個屬性可以記錄這個字段的物理位置。然后使用FieldByNumber來訪問字段。(是不是有點麻煩?我也是沒有辦法的辦法)。當然了,你也可以用一個列表按原始順序記錄Fields的。
 
TDataSet里的記錄號即RecNo這個屬性是用來表示當前可以訪問的所以記錄中按當前訪問順序的第RecNo個記錄。感知控件的顯示也依賴于這個屬性。它不是用來表示記錄的物理順序的。因此,在實現的時候,內部管理記錄時要另外使用一個成員變量來表示,相當于一個內部游標。
 
另外有幾個在《開發指南》中沒有提到的方法我想說明一下,這幾個都與感知控件的顯示有關,因此都在Public下的。
 
IsSquenced這個在TDataSet中Public下的函數,應該繼承一下。該方法是用來表示記錄的組織是否是連續緊湊的。這個特性在數據庫感知控件中會使用到。比如DBGrid中的垂直滾動條的狀態就是根據這個來決定的。如果該函數返回真,就是說記錄是緊湊的,則滾動條會根據RecNo來決定具體位置。反之,如果是假,則滾動條只有三個狀態,即最上、中間、最下。
 
CompareBookmark這個函數,使用來判斷兩個記錄的大小的。同樣,這個函數也與感知控件有關。在DBGrid選擇了MultiSelect后,當選擇了一條記錄后,Grid會根據該函數的返回值來決定是否選中鄰近的記錄。其實一句話,就是說Grid在這種狀態下,會選擇所有的相同記錄。
 
另外有一個函數,GetCanModify是實現特性CanModify的。覆蓋一下可以用來控制DataSet的ReadOnly。
 
對在第三段我說的TempBuffer我想在補充幾句。TempBuffer這個緩沖區具有很大的作用的,因為它擁有與其他緩沖區相同的特性與操作,而且它對你來說是“生存期自管理”的。這一點在你實現查詢操作時會發現很有用。你應該已經有了比較兩條記錄的函數,但是在查詢時,你只有一條記錄以及查詢條件可以使用。這是你可以將你的查詢條件轉換成記錄,而這條記錄就可以放到TempBuffer中。這樣你的實現就會變得很統一,因為你做的只是兩條記錄的比較。
 
TDataSet另外封裝了一點就是書簽功能(Bookmark)。一般情況下,Bookmark只要有兩個成員變量就行了。一個是Data(TBookmark類型),一個是Flag(TBookmarkFlag)。
Data使用來記錄你可以借此而訪問到該記錄的值。這是個Pointer類型的變量。因此,你可以把它作為整數使用(如存放記錄號,我就是這樣用的),也可以指向一個記錄的指針,甚至于一個記錄。而Flag是用來記錄當前標簽的位置。在Delphi中TbookmarkFlag是這樣定義的:TBookmarkFlag = (bfCurrent, bfBOF, bfEOF, bfInserted);其中bfCurrent是表示當前位置,即有效Data。BfBOF和bfEOF表示首尾位置。BfInserted表示剛剛插入還沒有提交(Post)的記錄。
   
    理解了Bookmark所需要的成員變量以及其意義。我們看一下在TDataSet中Delphi是如何使用Bookmark的。為了便于說明,我先介紹一下我在實現GDB時使用的Bookmark。
   
下面是結構:
    PGDBBookmarkInfo = ^TGDBBookmarkInfo;
    TGDBBookmarkInfo = record
       BookmarkData: Integer;
       BookmarkFlag: TbookmarkFlag;
    End;
   
   首先要解決的是Bookmark放在什么地方。這其實對外也是看不見的。上面講到記錄緩沖區,其實Bookmark就是接在記錄緩沖區后的。或者更簡單的說,整個緩沖區是由記錄和Bookmark(TGDBBookmarkInfo結構)組成的。
   
    記錄緩沖
書簽(TGDBBookmarkInfo)
   
           圖2: 記錄緩沖區結構
   
    對緩沖區的操作是在TDataSet的派生類里實現的。有幾個抽象方法SetBookmarkFlag,SetBookmarkData,GetBookmarkData,GetBookmarkFlag。這幾個方法是直接對緩沖區操作的。
   
    TDataSet就是利用這些方法對Bookmark進行操作的。不過,一般設置Bookmark都是在繼承類里實現的。實現的位置其實是可以想象的到的。由于Bookmark和記錄緩沖區在一起,那么在對記錄緩沖區操作的時候(讀記錄到緩沖區的時候),也就是GetRecord函數中,你可以將與該記錄關聯的Bookmark寫入。正如上面討論到的,你必須在BookmarkData中填入相應的值。如我這里,就可以填入記錄號。以后可以用記錄號來訪問該記錄。
   
InternalGotoBookmark就是利用BookmarkData來定位到記錄的。InternalSetToRecord也是類似的操作。
 
另外一個由數據感知控件頻繁使用的就是CompareBookmarks。它的兩個參數就TBookmark類型的。你就是根據這個指針來訪問你存放的數據。象我的實現就可以使用Integer(Bookmark1^)來使用。另外,按照我的實現,GetRecNo也可以通過對ActiveBuffer(記錄當前活動的緩沖區)的訪問來獲得的。

上一篇:如何防止密碼框的密碼被人破譯

下一篇:運行期間生成代碼的動態執行

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 池州市| 梧州市| 永修县| 徐水县| 乌拉特后旗| 福清市| 上虞市| 郸城县| 额济纳旗| 辽中县| 信宜市| 碌曲县| 南开区| 弥渡县| 巴东县| 玛曲县| 安吉县| 应用必备| 丹凤县| 涟水县| 温宿县| 双城市| 孙吴县| 北海市| 怀化市| 普定县| 那曲县| 手机| 洛川县| 新龙县| 手游| 兴安县| 开封县| 商都县| 吉木萨尔县| 荃湾区| 泽普县| 泽普县| 屏东市| 从江县| 玛曲县|