【資料庫】MFC ODBC(二)

QingLiXueShi發表於2015-10-05

三、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。

 

相關文章