分类: C/C++
2008-08-07 18:54:16
CDataSet 头文件 template这个模板有两个参数:一个是数据对象类,另一个是绑定字段的数量。数据对象类由一组成员变量组成,对应着不同的数据库表的字段,例如:class CDataSet : public CRecordset { public: CDataSet(LPCSTR Table, CDatabase* pdb); T m_Data; // Attached object CString m_DefaultSQL; // Default SQL SELECT statement CString m_DefaultSort; // Default SQL ORDER BY clause CString m_DefaultFilter; // Default SQL WHERE clause // Operations public: virtual BOOL Search(LPCSTR Filter, LPCSTR Sort = NULL, BOOL bFail = FALSE); virtual BOOL DirectSearch(LPCSTR Filter, LPCSTR Sort = NULL, BOOL bFail = FALSE); virtual void LoadAll(CArray & A, int N = 0); virtual void SaveAll(CArray & A); virtual void Load(T& Data) { Data = m_Data; } virtual void Store(T& Data); // Implementation protected: virtual CString GetDefaultSQL() { return m_DefaultSQL; } virtual void DoFieldExchange(CFieldExchange* pFX); };
struct DataObj { CString Var1; CString Var2; int Var3; float Var4; // ...... // 成员函数 };如果将数据对象定义成一个类,而不是一个结构,就必须定义缺省的供类模板使用的构造函数并
CDataSet类中许多方法都使用SetStatus()函数,它的作用是显示一个沙漏以及在应用程序状 态条显示当前的操作状态。CDataSet实现 template CDataSet ::CDataSet(LPCSTR Table, CDatabase* pdb) : CRecordset(pdb) { m_nFields = M; m_DefaultSQL = Table; m_DefaultFilter = "%s"; } template BOOL CDataSet ::Search(LPCSTR Filter,LPCSTR Sort, BOOL bFail) { if ( IsOpen() ) Close(); SetStatus("Opening " m_DefaultSQL " ..."); if ( Filter ) m_strFilter.Format(m_DefaultFilter, Filter); else m_strFilter = ""; m_strSort = Sort; Open(); // Throw exception if record not found if ( bFail && IsEOF() ) THROW(new CMyException(m_DefaultSQL " record not found!")); return !IsEOF(); } template BOOL CDataSet ::DirectSearch(LPCSTR Filter, LPCSTR Sort, BOOL bFail) { if ( IsOpen() ) Close(); SetStatus("Opening " m_DefaultSQL " ..."); m_strFilter = Filter; m_strSort = Sort; Open(); // Throw exception if record not found if ( bFail && IsEOF() ) THROW(new CMyException(m_DefaultSQL " record not found!")); return !IsEOF(); } template void CDataSet ::LoadAll(CArray & A, int N) { SetStatus("Loading " m_DefaultSQL " ..."); A.RemoveAll(); while ( !IsEOF() && (N == 0 || A.GetSize() < N) ) { A.Add(m_Data); MoveNext(); } } template void CDataSet ::SaveAll(CArray & A) { SetStatus("Writing " m_DefaultSQL " ..."); for ( int i = 0;i < A.GetSize(); i ) { AddNew(); Store(A[i]); } } template void CDataSet ::Store(T& Data) { SetStatus("Updating " m_DefaultSQL " ..."); Edit(); m_Data = Data; Update(); } template void CDataSet ::Close() { CRecordset::Close(); SetStatus("Ready"); }
void SetStatus(const CString Msg) { CFrameWnd* pMainFrame = (CFrameWnd*)AfxGetMainWnd(); if ( pMainFrame ) { pMainFrame->SetMessageText(Msg); pMainFrame->UpdateWindow(); if ( strcmp(Msg, "Ready") == 0 ) pMainFrame->EndWaitCursor(); else pMainFrame->BeginWaitCursor(); } }当处理大量数据和执行复杂的查询时,这个函数特别有用。它告诉用户应用程序正在处理数据。
class CMyException: public CException { CString m_ErrorMsg; public: CMyException(int ErrMsgResourceID); CMyException(CString ErrMsg); BOOL GetErrorMessage(LPTSTR lpszError,? UINT nMaxError, PUINT pnHelpContext = NULL); }; CMyException::CMyException(int ResourceID) { m_ErrorMsg.LoadString(ResourceID); } CMyException::CMyException(CString ErrorMsg) { m_ErrorMsg = ErrorMsg; } BOOL CMyException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError, PUINT) { strncpy(lpszError, (LPCSTR)m_ErrorMsg, nMaxError); return TRUE; }在使用CDataSet类的应用程序中,对象可以被实例化如下:
CDataset这里“Table1”是数据库表的名字,“&db”指向一个打开的数据库,在大多数情况下(尤其是当使用事务处理时),实例创建数据库对象并且在打开记录机之前从外部打开数据库。 您是否注意到在Listing 2 的代码中有一件事情没有做?,对每一个数据类而言必须要单独实现DoFieldExchange()来建立一个数据对象成员和数据库字段之间的联接,Listing 3 中的代码告诉您如何为DataObj实现DoFieldExchange()。MySet("Table1", &db);
数据对象的 DoFieldExchange() 方法 void CDataSet以下是使用CDataSet的一个例子:::DoFieldExchange(CFieldExchange* pFX) { pFX->SetFieldType(CFieldExchange::outputColumn); RFX_Text(pFX, "VAR1", m_Data.Var1); RFX_Text(pFX, "VAR2", m_Data.Var2); RFX_Int(pFX, "VAR3", m_Data.Var3); RFX_Single(pFX, "VAR4", m_Data.Var4); }
CDatabase db; CArray为了测试例子,要创建一个系统数据源“Test”(MS Access Driver),指向Test.mdb,运行DbTest.exe,在菜单中选择 Test =〉DataSet。 下载本文示例代码A; TRY { db.Open("TEST"); // Create recordset object CDataSet MySet("Table1", &db); // Set default filter to var1 MySet.m_DefaultFilter = "Var1 = ''%s''"; MySet.Open(); // Load all of the records MySet.LoadAll(A); // Find some record if ( MySet.Search("Anything") ) { DataObj B; // Load, update, and store new record MySet.Load(B); B.Var1 = "Anything else?"; MySet.Store(B); } MySet.Close(); AfxMessageBox("Data is loaded!"); } CATCH_ALL(e) { e->ReportError(); } END_CATCH_ALL