最近寫delphi項目,用到的數據集中的dataset,一直修改exception啊,寫下過程。
在對數據集進行任何操作之前,首先要打開數據集。要打開數據集,可以把Active屬性設為True,例如:
CustTable.Active := True;
也可以調用Open函數,例如:CustQuery.Open;
要關閉數據集,可以把Active屬性設為False或者調用Close函數。
其次 如果有exception的話,就要判斷state,下面我列舉下state的值(這樣是我從網上找的)
State屬性是只讀的,下面列出了State屬性可能的值:
.dsInactive 數據集已關閉,不能訪問它的數據;
.dsBrowse 數據集已打開,可以瀏覽數據但不能修改數據;
.dsEdit 此時為編輯狀態,可以修改數據;
.dsInsert 此時可以插入一條新的記錄;
.dsSetKey 只適用於TTable和TClientDataSet,此時可以設置范圍和鍵值,並且可以調用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狀態,可以調用Insert或Append函數。不過,調用Insert或Append不一定會使數據集進入dsInsert狀態,還取決於CanModify屬性的值。 一旦進入了dsInsert狀態,用戶就可以在數據控件(一般是TDBGrid)中插入一條新的記錄,並給這條記錄輸入數據。 如果要通過編程來插入新的記錄,就要注意Insert和Append的區別。Insert將把一條新的記錄插入到當前記錄的前面,而Append將把一條新的記錄添加到數據集的末尾。 插入了新的記錄后,應當調用Post或在CachedUpdates屬性設為True的情況下調用ApplyUpdates把新的記錄寫到數據集中。 如果數據集是已建立了索引的Paradox或dBASE表,新記錄將自動移到恰當的位置。 如果數據集沒有建立索引,新記錄就插入到數據集的當前位置(Insert)或末尾(Append)。 6.7.3 刪除記錄 調用Delete函數將刪除當前記錄,並且使數據集回到dsBrowse狀態。如果窗體上有TDBNavigator構件的話,用戶可以單擊導航器上的“Delete”按鈕刪除當前記錄。當前記錄被刪除后,下一條記錄就成為當前記錄。 如果刪除的本來就是最后一條記錄,則前一條記錄成為當前記錄。 6.7.4 修改整條記錄 除了TDBGrid和TDBNavigator外,大部分數據控件只能工作於數據集的一個或幾個字段,而不是整條記錄。 不過,TDataSet提供了若干個方法可以直接修改整條記錄而不是單獨的字段,這些方法包括: .AppendRecord類似於Append,但可以給字段賦值,不需要調用Post; .InsertRecord類似於Insert,但可以給字段賦值,不需要調用Post; .SetFields對當前記錄的字段賦值,需要顯式地調用Post。 上述三個方法都要傳遞一個TVarRec類型的數組作為參數,該數組的每一個元素對應着一個字段的值。如果數組的元素個數小於數據集的字段個數,剩下字段的值就是NULL。 對於沒有建立索引的數據集來說,AppendRecord把一條新的記錄加到數據集的末尾。對於已建立索引的數據集來說,新記錄將自動移到一個恰當的位置。 SetFields用於對當前記錄的字段賦值。在調用SetFields之前,首先要調用Edit,使數據集進入dsEdit狀態。調用了SetFields后,需要顯式地調用Post函數。 調用SetFields時,如果您只想對部分字段賦值,讓其他字段的值保持不變,可以用NULL或NIL去賦值。 假設一個數據集中有五個字段,分別是Name、Capital、Continent、Area和Population,可以這樣對它們賦值: 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系列,列表如下: .BeforeOpen,AfterOpen發生在數據集打開前后; .BeforeClose,AfterClose發生在數據集關閉前后; .BeforeInsert,AfterInsert發生在插入了一條新的記錄前后; .BeforeEdit,AfterEdit 發生在進入dsEdit狀態前后; .BeforePost,AfterPost 發生在寫數據集的前后; .BeforeCancel,AfterCancel發生在取消修改的前后; .BeforeDelete,AfterDelete發生在刪除記錄的前后。 此外,當數據集中增加了一條新的記錄時就會觸發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屬性 TBDEDataSet的CacheBlobs屬性用於控制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句柄,調用BDE的API時要用到這個句柄; .DBLocale返回當前的國際語言驅動程序; .DBSession返回一個BDE會話期對象; .DatabaseName用於指定要訪問的數據庫; .SessionName用於指定一個BDE會話期對象。 這里詳細解釋一下DatabaseName屬性和SessionName屬性。如果應用程序要訪問遠程數據庫服務器如Sybase、Oracle或InterBase,應當用TDatabase構件來連接數據庫,此時,應當設置DatabaseName屬性指定要連接的數據庫,可以設為TDatabase構件的名稱。如果沒有顯式地使用TDatabase構件,DatabaseName屬性應當設為BDE 別名。對於Paradox和dBASE表來說,可以設為表的路徑。 SessionName屬性用於指定一個BDE會話期對象。如果應用程序沒有顯式地使用TSession構件,不必設置這個屬性。如果應用程序顯式地使用了多個TSession構件,應當設置SessionName屬性指定其中一個。 一般來說,應用程序用不到DBHandle、DBLocale和DBSession等屬性,除非要直接調用BDE的API。這三個屬性都是只讀的。 TDBDataSet中還有一個只讀的Provider屬性,它能夠返回一個IProvider接口。在多層的Client/Server應用程序中,客戶程序需要通過IProvider接口與應用服務器通訊。
|