|
本文描述了如何在MFC的文档/视图/框架架构中使用ADO和ADOX来创建和打开数据库。
预备阅读
在阅读本文之前,建议先对COM,数据库和MFC的文档/视图/框架有一个基本的了解。推荐阅读下列文章
MFC技术文章
- TN025: Document, View, and Frame Creation
微软知识库文章
- Q183606 ActiveX Data Objects (ADO) Frequently Asked Questions
- Q169496 INFO: Using ActiveX Data Objects (ADO) via #import in VC++
- Q317881 HOW TO: Create an Access Database Using ADOX and Visual C# .NET
- Q252908 HOWTO: Create a Table with Primary Key Through ADOX
- Q201826 PRB: Error 3265 When You Access Properties Collection
Office VBA参考
- Creating and Modifying Access Tables
步骤
- 在计算机上安装MDAC2.5以上版本
- 打开VC。首先,我们使用MFC应用程序向导创建一个标准的MDI程序,这里我为这个工程起名为Passport,然后在stdafx.h中导入ADOX
#include <shlwapi.h> #import "c:\Program Files\Common Files\system\ado\Msado15.dll" rename("EOF","adoEOF") rename("DataTypeEnum","adoDataTypeEnum") #import "c:\Program Files\Common Files\System\ADO\Msadox.dll" rename("EOF", "adoXEOF") rename("DataTypeEnum","adoXDataTypeEnum") #import "c:\PROGRAM FILES\COMMON FILES\System\ado\MSJRO.DLL"
根据你的计算机上ADO的安装路径,这里的路径可能有所不同。
- 在文档类中声明数据库连接 ADODB::_ConnectionPtr m_pConn;和记录集 ADODB::_RecordsetPtr m_pSet;,并且重载文档类的DeleteContents() 、OnNewDocument()和OnOpenDocument()函数,用于断开数据库连接,创建数据库和表,以及打开现有的数据库。
(作者的抱怨:CSDN文章中心该改改了,代码排版这么麻烦) void CPassportDoc::DeleteContents() { try { if(m_pSet){ ESRecordsetClose(m_pSet); } if(m_pConn) if(m_pConn->State&ADODB::adStateOpen) m_pConn->Close(); m_pConn=NULL; } catch(_com_error &e){ ESErrPrintProviderError(m_pConn); ESErrPrintComError(e); } CDocument::DeleteContents(); }BOOL CPassportDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; CFileDialog dlgFile(FALSE, _T(".mdb"), NULL, OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, _T("Access 数据库 (*.mdb)|*.mdb|全部文件(*.*)|*.*||")); if (dlgFile.DoModal() != IDOK) return FALSE; CString strDBPath=dlgFile.GetPathName(); if(!CreateDB(strDBPath))return FALSE; //create CString strConnect; strConnect.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s"),strDBPath); COleVariant Connect(strConnect); // TODO: add reinitialization code here // (SDI documents will reuse this document) try{ m_pConn.CreateInstance(_T("ADODB.Connection")); m_pSet.CreateInstance(_T("ADODB.Recordset")); m_pConn->PutCommandTimeout(30); m_pConn->PutConnectionTimeout(30); m_pConn->put_CursorLocation(ADODB::adUseClient); m_pConn->Open(_bstr_t(strConnect),_bstr_t(),_bstr_t(),ADODB::adConnectUnspecified); ::ESRecordsetOpen(_T("Passport"),m_pConn,m_pSet); SetPathName(strDBPath); return TRUE; } catch(_com_error &e){ ESErrPrintProviderError(m_pConn); ESErrPrintComError(e); } catch(...){ } m_pConn=NULL; return FALSE; } BOOL CPassportDoc::OnOpenDocument(LPCTSTR lpszPathName) { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; ADODB::_ConnectionPtr tempConnn; CString strConnect; CString strDBPath=lpszPathName; strConnect.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s"),strDBPath); COleVariant Connect(strConnect); // TODO: add reinitialization code here // (SDI documents will reuse this document) try{ tempConnn.CreateInstance(_T("ADODB.Connection")); tempConnn->PutCommandTimeout(30); tempConnn->PutConnectionTimeout(30); tempConnn->put_CursorLocation(ADODB::adUseClient); tempConnn->Open(_bstr_t(strConnect),_bstr_t(),_bstr_t(),ADODB::adConnectUnspecified); SetPathName(strDBPath); m_pConn=tempConnn; m_pSet=NULL; m_pSet.CreateInstance(_T("ADODB.Recordset")); ::ESRecordsetOpen(_T("Passport"),m_pConn,m_pSet); UpdateAllViews(NULL,UpdateHintRefresh); return TRUE; } catch(_com_error &e){ ESErrPrintProviderError(tempConnn); ESErrPrintComError(e); } catch(...){ } return FALSE; }
- 编写一个辅助函数,用于创建数据库、表和索引
BOOL CPassportDoc::CreateDB(LPCTSTR lpszFile) { if(::PathFileExists(lpszFile)){ CString strTemp; strTemp.Format(IDS_TARGET_EXISTS,lpszFile); AfxMessageBox(lpszFile); return FALSE; } ADODB::_ConnectionPtr tempConnn; ADOX::_CatalogPtr pCatalog = NULL; ADOX::_TablePtr pTable = NULL; ADOX::_IndexPtr pIndexNew = NULL; ADOX::_IndexPtr pIndex = NULL; CString strConnect; CString strDBPath=lpszFile; strConnect.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s"),strDBPath); COleVariant Connect(strConnect); try{ pCatalog.CreateInstance(_T("ADOX.Catalog")); pCatalog->Create((LPCTSTR)strConnect);//创建数据库 tempConnn.CreateInstance(_T("ADODB.Connection")); tempConnn->PutCommandTimeout(30); tempConnn->PutConnectionTimeout(30); tempConnn->put_CursorLocation(ADODB::adUseClient); tempConnn->Open(_bstr_t(strConnect),_bstr_t(),_bstr_t(),ADODB::adConnectUnspecified); pCatalog->PutActiveConnection(_variant_t((IDispatch *) tempConnn)); pTable.CreateInstance(_T("ADOX.Table")); pTable->ParentCatalog =pCatalog; pTable->Name="Passport"; ADOX::ColumnsPtr pCols =pTable->Columns; pCols->Append(_T("RecordID") ,ADOX::adInteger,0);//自动编号字段 pCols->Append(_T("Name") ,ADOX::adWChar,255);//文本字段 pCols->Append(_T("DateOfBirth") ,ADOX::adDate,0);//日期字段 pCols->Append(_T("OtherInfo"),ADOX::adLongVarWChar,0);//备注字段 pCatalog->Tables->Refresh(); long lCount=pCols->Count; for(long i=0;i<lCount;i++){ pCols->GetItem(i)->ParentCatalog =pCatalog;//重要!设置Catalog,参见Q201826 PRB: Error 3265 When You Access Properties Collection ADOX::PropertiesPtr pProperties=pCols->GetItem(i)->Properties; if(pProperties){//这里是用于调试的属性显示代码 long lp=pProperties->Count; TRACE("Properties for Col %s\r\n",(LPCTSTR)pCols->GetItem(i)->Name); for(long j=0;j<lp;j++){ TRACE("\rProperty %s:%s\r\n",g_GetValueString(pProperties->GetItem(j)->Name) ,g_GetValueString(pProperties->GetItem(j)->Value)); } } } pCols->GetItem(_T("RecordID"))->Properties->GetItem(_T("Description"))->Value=_T("记录编号");//注释 pCols->GetItem(_T("RecordID"))->Properties->GetItem(_T("AutoIncrement"))->Value=true;//自动编号 pCols->GetItem(_T("Name"))->Properties->GetItem(_T("Jet OLEDB:Compressed UniCode Strings"))->Value=true; pCols->GetItem(_T("Name"))->Properties->GetItem(_T("Description"))->Value=_T("姓名"); pCols->GetItem(_T("DateOfBirth"))->Properties->GetItem(_T("Description"))->Value=_T("出生日期"); pCols->GetItem(_T("OtherInfo"))->Properties->GetItem(_T("Jet OLEDB:Compressed UniCode Strings"))->Value=true; pCols->GetItem(_T("OtherInfo"))->Properties->GetItem(_T("Description"))->Value=_T("其他信息"); pCatalog->Tables->Append(_variant_t ((IDispatch*)pTable));//添加表 pCatalog->Tables->Refresh();//刷新 pIndexNew.CreateInstance(_T("ADOX.Index")); pIndexNew->Name = "RecordID";//索引名称 pIndexNew->Columns->Append("RecordID",ADOX::adInteger,0);//索引字段 pIndexNew->PutPrimaryKey(-1);//主索引 pIndexNew->PutUnique(-1);//唯一索引 pTable->Indexes->Append(_variant_t ((IDispatch*)pIndexNew));//创建索引 pIndexNew=NULL; pCatalog->Tables->Refresh();//刷新 return TRUE; } catch(_com_error &e){ ESErrPrintProviderError(tempConnn); ESErrPrintComError(e); return FALSE; } catch(...){ } return FALSE; }
- 辅助的数据库函数。由于这些函数是Jiangsheng以前为一个项目写的。所以命名有些奇怪。借鉴了MFC类CDaoRecordset的部分代码
#define _countof(array) (sizeof(array)/sizeof(array[0])) BOOL ESRecordsetOpen( LPCTSTR lpszSQL ,ADODB::_ConnectionPtr pConnection ,ADODB::_RecordsetPtr& rst ,ADODB::CursorTypeEnum CursorType//=adOpenDynamic ,ADODB::LockTypeEnum LockType//=ado20::adLockOptimistic ,long lOptions//=adCmdUnspecified ) { [1] [2] 下一页 |