delphi中 dataset容易出錯的地方


 最近寫delphi項目,用到的數據集中的dataset,一直修改exception啊,寫下過程。

 

 在對數據集進行任何操作之前,首先要打開數據集。要打開數據集,可以把Active屬性設為True,例如:
  CustTable.Active := True;
  也可以調用Open函數,例如:CustQuery.Open;
  要關閉數據集,可以把Active屬性設為False或者調用Close函數。

其次 如果有exception的話,就要判斷state,下面我列舉下state的值(這樣是我從網上找的)

State屬性是只讀的,下面列出了State屬性可能的值:
.dsInactive 數據集已關閉,不能訪問它的數據;
.dsBrowse 數據集已打開,可以瀏覽數據但不能修改數據;
.dsEdit 此時為編輯狀態,可以修改數據;
.dsInsert 此時可以插入一條新的記錄;
.dsSetKey 只適用於TTableTClientDataSet,此時可以設置范圍和鍵值,並且可以調用GotoKey函數;
.dsCalcFields 正在處理OnCalcFields事件(當字段需要指定一個值的時候促發的事件),此時不能修改非計算字段的值;
.dsCurValue 內部使用;
.dsNewValue 內部使用;
.dsOldValue 內部使用;
.dsFilter 正在進行過濾操作。 

當我看到我的項目的state為 dsInactive ,被踢我有多高行啦,然后立馬改為dsedit,尼瑪。但是還不管用,然后又看到方法:

如果應用程序要修改數據集的數據,必須首先進入dsEdit狀態。要進入dsEdit狀態,可以調用Edit。不過,調用Edit並不能保證一定能進入dsEdit狀態,這還取決於CanModify屬性的值。如果這個屬性返回True的話,表示數據集是可以讀和寫的。

終於完成了,尼瑪,就因為這被經理說,效率慢,該錯誤還是比較容易的,但是exception,就不是那么簡單。下面補充下dataset的其他state的介紹:

下面的功能我是沒用到的::

 

 

6.7.2 插入新的記錄
  要在數據集中插入新的記錄,首先要進入dsInsert狀態。要進入dsInsert狀態,可以調用InsertAppend函數。不過,調用InsertAppend不一定會使數據集進入dsInsert狀態,還取決於CanModify屬性的值。
  一旦進入了dsInsert狀態,用戶就可以在數據控件(一般是TDBGrid)中插入一條新的記錄,並給這條記錄輸入數據。
  如果要通過編程來插入新的記錄,就要注意InsertAppend的區別。Insert將把一條新的記錄插入到當前記錄的前面,而Append將把一條新的記錄添加到數據集的末尾。
  插入了新的記錄后,應當調用Post或在CachedUpdates屬性設為True的情況下調用ApplyUpdates把新的記錄寫到數據集中。
  如果數據集是已建立了索引的ParadoxdBASE表,新記錄將自動移到恰當的位置。
  如果數據集沒有建立索引,新記錄就插入到數據集的當前位置(Insert)或末尾(Append)
6.7.3 刪除記錄
  調用Delete函數將刪除當前記錄,並且使數據集回到dsBrowse狀態。如果窗體上有TDBNavigator構件的話,用戶可以單擊導航器上的“Delete”按鈕刪除當前記錄。當前記錄被刪除后,下一條記錄就成為當前記錄。
  如果刪除的本來就是最后一條記錄,則前一條記錄成為當前記錄。
6.7.4 修改整條記錄
  除了TDBGridTDBNavigator外,大部分數據控件只能工作於數據集的一個或幾個字段,而不是整條記錄。
  不過,TDataSet提供了若干個方法可以直接修改整條記錄而不是單獨的字段,這些方法包括:
.AppendRecord類似於Append,但可以給字段賦值,不需要調用Post;
.InsertRecord類似於Insert,但可以給字段賦值,不需要調用Post;
.SetFields對當前記錄的字段賦值,需要顯式地調用Post
  上述三個方法都要傳遞一個TVarRec類型的數組作為參數,該數組的每一個元素對應着一個字段的值。如果數組的元素個數小於數據集的字段個數,剩下字段的值就是NULL
  對於沒有建立索引的數據集來說,AppendRecord把一條新的記錄加到數據集的末尾。對於已建立索引的數據集來說,新記錄將自動移到一個恰當的位置。
  SetFields用於對當前記錄的字段賦值。在調用SetFields之前,首先要調用Edit,使數據集進入dsEdit狀態。調用了SetFields后,需要顯式地調用Post函數。
  調用SetFields時,如果您只想對部分字段賦值,讓其他字段的值保持不變,可以用NULLNIL去賦值。
  假設一個數據集中有五個字段,分別是NameCapitalContinentAreaPopulation,可以這樣對它們賦值:
CountryTable.InsertRecord([Japan, Tokyo, Asia]);
  上述程序在數據集中插入了一條新的記錄,並且對前三個字段賦了值。現在可以再次對當前記錄賦值,不過,這次只想對Area字段和Population字段賦值,程序就要這樣寫:
With CountryTable Do
Begin
If Locate(Name, Japan, loCaseInsensitive) then
Begin
Edit;
SetFields(NIL, NIL, NIL, 344567, 164700000);
Post;
End;
End;
  注意:此處要用NIL而不是NULL,否則,前三個字段會被設為空。
6.8 事 件
  TDataSet的事件主要分為兩大類,一類是Before系列,另一類是After系列,列表如下:
.BeforeOpenAfterOpen發生在數據集打開前后;
.BeforeCloseAfterClose發生在數據集關閉前后;
.BeforeInsertAfterInsert發生在插入了一條新的記錄前后;
.BeforeEditAfterEdit 發生在進入dsEdit狀態前后;
.BeforePostAfterPost 發生在寫數據集的前后;
.BeforeCancelAfterCancel發生在取消修改的前后;
.BeforeDeleteAfterDelete發生在刪除記錄的前后。
  此外,當數據集中增加了一條新的記錄時就會觸發OnNewRecord事件,當計算字段的值需要重算時將觸發OnCalcFields事件。
  Before系列的事件常常用來中止操作。例如,當調用Delete函數試圖刪除當前記錄時,在當前記錄將要刪除前會觸發BeforeDelete事件,可以在處理BeforeDelete事件的句柄中調用Abort或觸發一個異常放棄刪除當前記錄,程序示例如下:
Pocedure TForm1.TableBeforeDelete (Dataset: TDataset)
Begin
If MessageDlg(Delete This Record?, mtConfirmation, mbYesNoCancel, 0) <> mrYes Then Abort;
End;
  After系列的事件往往用來在狀態欄上通知用戶,程序示例如下:
Procedure TForm1.Table1AfterDelete(DataSet: TDataSet);
Begin
StatusBar1.SimpleText := Format(%d 條記錄,[DataSet.RecordCount]);
End;
  OnCalcFields事件主要用於給出計算字段的值。AutoCalcFields屬性的值決定了什么時候會發生OnCalcFields事件。
  如果AutoCalcFields屬性設為True,下列情況下會發生OnCalcFields事件:
.數據集被打開時;
.在數據控件中,輸入焦點從一條記錄移到另一條記錄;
.在數據控件中,輸入焦點從一個字段移到另一個字段;
.當前記錄被修改或從數據庫中檢索了一條記錄。
  不過,即使AutoCalcFields屬性設為False,當數據集中的任意一個非計算字段的值發生變化時都會觸發OnCalcFields事件。
  由於OnCalcFields事件有可能是頻繁發生的,因此,處理OnCalcFields 事件的代碼要盡可能地簡短。在AutoCalcFields屬性設為True的情況下,在處理OnCalcFields事件的句柄中不能修改數據集的數據,因為一旦當前記錄被修改,又要觸發OnCalcFields事件,從而導致無限循環。例如,假設您在處理OnCalcFields事件的句柄中調用了Post,就會觸發OnCalcFields事件,導致再次調用Post,再次觸發OnCalcFields事件……
6.9 TBDEDataSet
  TBDEDataSet是從TDataSet繼承下來的,它提供了通過BDE(BorlandDatabase Engine)訪問數據的能力。這一節主要介紹TBDEDataSet,讀者應當對前面介紹的TDataSet已經有了比較深刻的認識。
  與TDataSet一樣,TBDEDataSet也是虛擬的和抽象的,除非您想建立自定義的數據集,否則,一般不需要直接用到TBDEDataSet
  TBDEDataSet重載了TDataSet中涉及記錄導航、索引和書簽的方法,增加了一些處理BLOB字段、緩存更新的屬性、方法和事件。
6.9.1 CacheBlobs屬性
  TBDEDataSetCacheBlobs屬性用於控制BDE是否把BLOB字段的內容放到緩存中。如果這個屬性設為True,當應用程序讀取BLOB字段的值時,BDE將把BLOB字段的內容放在緩存中,這樣,當應用程序下次要讀取這個字段的值時,就不必再從數據庫服務器那兒去檢索,只要直接從內存中取過來就行了,這樣可以提高應用程序的性能。
  不過,如果應用程序需要頻繁地更新BLOB字段的值,這時候反而應當把CacheBlobs屬性設為False,這樣能保證檢索到的BLOB字段的值總是最新的。
6.9.2 緩存更新
  TBDEDataSet提供了緩存更新的技術。所謂緩存更新就是,應用程序從數據庫中檢索數據,在本地緩存中建立一個副本,用戶對數據進行修改后,也只是反映在緩存中,以后可以調用ApplyUpdates一次性地把所有的修改反映到數據集中。
  可以看出,緩存更新技術可以明顯地提高應用程序的性能,而且可以方便地取消修改,只要還沒有調用ApplyUpdates。下面列出了TBDEDataSet中有關緩存更新的屬性、方法和事件:
.CachedUpdates如果這個屬性設為True,緩存更新有效;
.UpdateObject用於指定一個TUpdateSQL構件來更新基於查詢的數據集;
.UpdatePending如果緩存中有未決的記錄,這個屬性就返回True;
.UpdateRecordTypes指定數據集中哪些記錄是可見的;
.UpdateStatus返回當前的更新狀態;
.OnUpdateError如果更新過程中出錯將觸發這個事件;
.OnUpdateRecord每更新一條記錄就會觸發一次這個事件;
.ApplyUpdates把緩存中的數據寫到數據集中;
.CancelUpdates把緩存中未決的修改取消;
.CommitUpdates把緩存清掉;l FetchAll從數據庫檢索所有記錄到緩存中;
.RevertRecord撤消對當前記錄的修改。
6.10 TDBDataSet
  TDBDataSet是從TBDEDataSet繼承下來的,它提供了數據庫和會話期管理的能力。
  TDBDataSet中增加了若干個屬性和方法用於管理數據庫和BDE會話期,包括:
.CheckOpen檢查數據庫是否已打開;
.Database返回一個TDatabase構件;
.DBHandle返回一個BDE句柄,調用BDEAPI時要用到這個句柄;
.DBLocale返回當前的國際語言驅動程序;
.DBSession返回一個BDE會話期對象;
.DatabaseName用於指定要訪問的數據庫;
.SessionName用於指定一個BDE會話期對象。
  這里詳細解釋一下DatabaseName屬性和SessionName屬性。如果應用程序要訪問遠程數據庫服務器如SybaseOracleInterBase,應當用TDatabase構件來連接數據庫,此時,應當設置DatabaseName屬性指定要連接的數據庫,可以設為TDatabase構件的名稱。如果沒有顯式地使用TDatabase構件,DatabaseName屬性應當設為BDE 別名。對於ParadoxdBASE表來說,可以設為表的路徑。
  SessionName屬性用於指定一個BDE會話期對象。如果應用程序沒有顯式地使用TSession構件,不必設置這個屬性。如果應用程序顯式地使用了多個TSession構件,應當設置SessionName屬性指定其中一個。
  一般來說,應用程序用不到DBHandleDBLocaleDBSession等屬性,除非要直接調用BDEAPI。這三個屬性都是只讀的。
  TDBDataSet中還有一個只讀的Provider屬性,它能夠返回一個IProvider接口。在多層的Client/Server應用程序中,客戶程序需要通過IProvider接口與應用服務器通訊。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM