天天看點

【資料庫】MFC ODBC(二)

三、CRecordset類

1、IsBOF與IsEOF

(1)IsBOF

如果記錄集沒有記錄,或已經向前遊動到第一個記錄之前,則傳回非零;否則傳回0。詳細說明如下:

1)通路Open函數之後,如果記錄集沒有任何記錄,IsBOF傳回非零。當你打開一個至少包含一個記錄的記錄集,第一個記錄是目前記錄,此時IsBOF傳回0。

2)如果第一個記錄是目前記錄并且你通路MovePrev,之後IsBOF會傳回非零值。如果IsBOF傳回非零值并且通路MovePrev函數,會報錯。

3)如果IsBOF傳回非零值,說明目前記錄沒有定義,任何請求目前記錄的動作将會導緻錯誤。

(2)IsEOF

如果記錄集沒有記錄,或已經滾動到最後一條紀錄之後,則傳回非零。否則,傳回0。

if (m_test.IsOpen())
    m_test.Close();
m_test.Open();

//如果記錄集為空,傳回
if (m_test.IsBOF())
    return FALSE;

//如果不是最後一個記錄的下一個位置,就向下移動一個記錄
while (!m_test.IsEOF) {
    m_test.MoveNext();
}      

2、快照(Snapshot) 和動态集(Dynaset)

在多任務作業系統或網絡環境中,多個使用者可以共享同一個資料源。共享資料的一個主要問題是如何協調各個使用者對資料源的修改。例如,當某一個應用改變了資料源中的記錄時,别的連接配接至該資料源的應用應該如何處理。對于這個問題,基于MFC的ODBC應用程式可以采取幾種不同的處理辦法,這将由程式采用哪種記錄集決定。

記錄集主要分為快照(Snapshot) 和動态集(Dynaset)兩種,CRecordset類對這兩者都支援。這兩種記錄集的不同表現在它們對别的應用改變資料源記錄采取了不同的處理方法。

(1)快照(Snapshot) 

快照型記錄集提供了對資料的靜态視。當别的使用者改變了記錄時(包括修改、添加和删除),快照中的記錄不受影響,也就是說,快照不反映别的使用者對資料源記錄的改變,直到調用了CRecordset::Requery重新查詢後,快照才會反映變化。需要指出的是,快照的這種靜态特性是相對于别的使用者而言的,它會正确反映由本身使用者對記錄的修改和删除,但對于新添加的記錄直到調用Requery後才能反映到快照中。

(2)動态集(Dynaset)

動态集提供了資料的動态視。當别的使用者修改或删除了記錄集中的記錄時,會在動态集中反映出來:當滾動到修改過的記錄時對其所作的修改會立即反映到動态集中,當記錄被删除時,MFC代碼會跳過記錄集中的删除部分。對于其它使用者添加的記錄,直到調用Requery時,才會在動态集中反映出來。本身應用程式對記錄的修改、添加和删除會反映在動态集中。當資料必須是動态的時侯,使用動态集是最适合的。例如,在一個火車票聯網售票系統中,顯然應該用動态集随時反映出共享資料的變化。

(3)光标機制

在記錄集中滾動,需要有一個标志來指明滾動後的位置(目前位置)。ODBC驅動程式會維護一個光标,用來跟蹤記錄集的目前記錄,可以把光标了解成跟蹤記錄集位置的一種機制。

光标庫(Cursor Library)是處于ODBC驅動程式管理器和驅動程式之間的動态連結庫(ODBCCR32.DLL)。光标庫的主要功能是支援快照以及為底層驅動程式提供雙向滾動能力,高層次的驅動程式不需要光标庫,因為它們是可滾動的。光标庫管理快照記錄的緩沖區,該緩沖區反映本程式對記錄的修改和删除,但不反映其它使用者對記錄的改變,由此可見,快照實際上相當于目前的光标庫緩沖區。

快照是一種靜态光标(Static Cursor)。靜态光标直到滾動到某個記錄才能取得該記錄的資料。是以,要保證所有的記錄都被快照,可以先滾動到記錄集的末尾,然後再滾動到感興趣的第一個記錄上。這樣做的缺點是滾動到末尾需要額外的開銷,會降低性能。

與快照不同,動态集不用光标庫維持的緩沖區來存放記錄。實際上,動态集是不使用光标庫的,因為光标庫會屏蔽掉一些支援動态集的底層驅動程式功能。動态集是一種鍵集驅動光标(Keyset-Driven Cursor),當打開一個動态集時,驅動程式儲存記錄集中每個記錄的鍵。隻要光标在動态集中滾動,驅動程式就會通過鍵來從資料源中檢取目前記錄,進而保證選取的記錄與資料源同步。

從上面的分析中可以看出,快照和動态集有一個共同的特點,那就是在建立記錄集後,記錄集中的成員就已經确定了。這就是為什麼兩種記錄集都不能反映别的使用者添加記錄的原因。

3、Open與Requery

CRecordSet的Open()和Requery()成員函數可以實作記錄查詢。詳細說明如下:

(1)使用CRecordSet的類對象之前,必須使用CRecordSet的成員函數Open()來獲得有效的記錄集。一旦使用過Open()函數,再次查詢時使用Requery()函數就可以了。

(2)調用Open()函數時,如果已經将一個打開的CDatabase對象指針傳遞給CRecordSet類對象的m_pDatabase成員變量,那麼,CRecordSet類對象将使用該資料庫對象建立ODBC連接配接;否則,如果m_pDatabase為空指針,對象就需要就建立一個CDatabase類對象并使其與預設的資料源相連,然後進行CRecordSet類對象的初始化。預設資料源由GetDefaultConnect()函數獲得。

(3)也可以提供所需要的SQL語句,并以它來調用CRecordSet::Open()函數,例如:

//strSQL為SQL語句
m_test.Open(AFX_DB_USE_DEFAULT_TYPE, strSQL);      

(4)如果Open沒有指定參數,程式使用預設的SQL語句,即對在GetDefaultSQL()函數中指定的SQL語句進行操作。例如:

CString CHistorySet::GetDefaultSQL()
{
    return _T("[History]");
}      

GetDefaultSQL()函數傳回的表名,對應的預設操作是SELECT語句,即:SELECT *FROM History。