结合ADO、ADOX和MFC的文档/视图/框架架构创建和打开Access数据库
本文描述了如何在MFC的文档/视图/框架架构中使用ADO和ADOX来创建和打开数据库。 预备阅读 MFC技术文章 TN025: Document, View, and Frame Creation 微软知识库文章 Q183606 ActiveX Data Objects (ADO) Frequently Asked Questions Q169496 INFO: Using Acti
本文描述了如何在MFC的文档/视图/框架架构中使用ADO和ADOX来创建和打开数据库。
预备阅读
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
#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;ipCols->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;jTRACE("/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
)
{
_bstr_t bstrQuery;
const TCHAR _afxParameters2[] = _T("PARAMETERS ");
const TCHAR _afxSelect2[] = _T("SELECT ");
const TCHAR _afxTransform2[] = _T("TRANSFORM ");
const TCHAR _afxTable2[] = _T("TABLE ");
// construct the default query string
if ((_tcsnicmp(lpszSQL, _afxSelect2, _countof(_afxSelect2)-1) != 0) &&
(_tcsnicmp(lpszSQL, _afxParameters2, _countof(_afxParameters2)-1) != 0) &&
(_tcsnicmp(lpszSQL, _afxTransform2, _countof(_afxTransform2)-1) != 0) &&
(_tcsnicmp(lpszSQL, _afxTable2, _countof(_afxTable2)-1) != 0)){
CString strTemp;
strTemp.Format("SELECT * FROM (%s)",lpszSQL);
bstrQuery=(LPCTSTR)strTemp;
}
else
bstrQuery=lpszSQL;
if(rst!=NULL){
rst->CursorLocation=ADODB::adUseClient;
rst->Open(bstrQuery,_variant_t(pConnection.GetInterfacePtr(),true),CursorType,LockType,lOptions);
}
TRACE("Open Recordset:%s/n",lpszSQL);
return ESRecordsetIsOpen(rst);
}
BOOL ESRecordsetIsOpen(const ADODB::_RecordsetPtr& rst)
{
if(rst!=NULL){
return rst->State&ADODB::adStateOpen;
}
return FALSE;
}
void ESRecordsetClose(ADODB::_RecordsetPtr& rst)
{
if(rst!=NULL){
if(rst->State&ADODB::adStateOpen)
rst->Close();
}
}
CString g_GetValueString(const _variant_t& val)
{
CString strVal;
_variant_t varDest(val);
if(!g_varIsValid(val)){
return strVal;
}
if(val.vt==VT_BOOL){
if(val.boolVal==VARIANT_FALSE){
return _T("否");
}
else
return _T("是");
}
else{
}
if(varDest.vt!=VT_BSTR){
HRESULT hr=::VariantChangeType(&varDest,&varDest,VARIANT_NOUSEROVERRIDE|VARIANT_LOCALBOOL,VT_BSTR);
if(FAILED(hr)){
return strVal;
}
}
strVal=(LPCTSTR)_bstr_t(varDest);
return strVal;
} - 错误处理代码
void ESErrPrintComError(_com_error &e)
{
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
CString strTemp;
strTemp.Format(_T("´错误/n/t错误代码: %08lx/n/t含义: %s/n/t来自 : %s/n/t描述 : %s/n"),
e.Error(),e.ErrorMessage(),(LPCSTR) bstrSource,(LPCSTR) bstrDescription);
// Print COM errors.
::AfxMessageBox(strTemp);
#ifdef _DEBUG
AfxDebugBreak();
#endif
}
void ESErrPrintProviderError(ADODB::_ConnectionPtr pConnection)
{
if(pConnection==NULL) return;
try{
// Print Provider Errors from Connection object.
// pErr is a record object in the Connection's Error collection.
ADODB::ErrorPtr pErr = NULL;
ADODB::ErrorsPtr pErrors=pConnection->Errors;
if(pErrors){
if( (pErrors->Count) > 0){
long nCount = pErrors->Count;
// Collection ranges from 0 to nCount -1.
for(long i = 0;i pErr = pErrors->GetItem(i);
CString strTemp;
strTemp.Format(_T("/t 错误代码: %x/t%s"), pErr->Number, pErr->Description);
}
}
}
}
catch(_com_error &e){
ESErrPrintComError(e);
}
}
总结
在文档/视图/框架架构中集成数据库访问总体来说还是难度不大的。微软提供了很多示例的代码,大部分工作只是把示例代码从其他语言改写到VC。主要的工作是对MFC的文档/视图/框架架构的理解,在适当的时候调用这些代码。
尽管我在打开数据库的同时也打开了一个记录集,但是我并未给出显示记录集内容的代码,这超出了本文的范围。我可以给出的提示是使用现成的数据列表控件来显示,微软知识库文章Q229029 SAMPLE: AdoDataGrid.exe Demonstrates How to Use ADO with DataGrid Control Using Visual C++可以作为参考。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Go 프레임워크 아키텍처의 학습 곡선은 Go 언어 및 백엔드 개발에 대한 친숙도와 선택한 프레임워크의 복잡성, 즉 Go 언어의 기본 사항에 대한 올바른 이해에 따라 달라집니다. 백엔드 개발 경험이 있으면 도움이 됩니다. 다양한 복잡성의 프레임워크는 다양한 학습 곡선으로 이어집니다.

Java 프레임워크에 대한 상용 지원의 비용/성능 평가에는 다음 단계가 포함됩니다. 필요한 보증 수준과 SLA(서비스 수준 계약) 보장을 결정합니다. 연구지원팀의 경험과 전문성. 업그레이드, 문제 해결, 성능 최적화와 같은 추가 서비스를 고려하십시오. 위험 완화 및 효율성 향상을 기준으로 비즈니스 지원 비용을 평가합니다.

위 작성 및 저자 개인 이해: 최근 딥러닝 기술의 발전과 획기적인 발전으로 대규모 기반 모델(Foundation Models)이 자연어 처리 및 컴퓨터 비전 분야에서 상당한 성과를 거두었습니다. 자율주행에 기본 모델을 적용하는 것도 시나리오에 대한 이해와 추론을 향상시킬 수 있는 큰 발전 전망을 가지고 있습니다. 풍부한 언어와 시각적 데이터에 대한 사전 학습을 통해 기본 모델은 자율주행 시나리오의 다양한 요소를 이해하고 해석하고 추론을 수행할 수 있으며, 의사 결정 및 계획을 추진하기 위한 언어 및 동작 명령을 제공합니다. 기본 모델은 일상적인 운전 및 데이터 수집 중에 발생할 가능성이 없는 롱테일 분포에서 드물게 실행 가능한 기능을 제공하기 위해 운전 시나리오에 대한 이해를 통해 데이터를 보강할 수 있습니다.

PHP 프레임워크의 학습 곡선은 언어 숙련도, 프레임워크 복잡성, 문서 품질 및 커뮤니티 지원에 따라 달라집니다. PHP 프레임워크의 학습 곡선은 Python 프레임워크에 비해 높고 Ruby 프레임워크에 비해 낮습니다. Java 프레임워크에 비해 PHP 프레임워크는 학습 곡선이 적당하지만 시작하는 데 걸리는 시간이 더 짧습니다.

경량 PHP 프레임워크는 작은 크기와 낮은 리소스 소비를 통해 애플리케이션 성능을 향상시킵니다. 그 특징은 다음과 같습니다: 작은 크기, 빠른 시작, 낮은 메모리 사용량, 향상된 응답 속도 및 처리량, 리소스 소비 감소 실제 사례: SlimFramework는 500KB에 불과한 REST API를 생성하며 높은 응답성과 높은 처리량을 제공합니다.

Golang 프레임워크에서는 명확하고 포괄적인 문서를 작성하는 것이 중요합니다. 모범 사례에는 Google의 Go 코딩 스타일 가이드와 같은 확립된 문서 스타일을 따르는 것이 포함됩니다. 제목, 부제, 목록 등 명확한 조직 구조를 사용하고 탐색 기능을 제공하세요. 시작 안내서, API 참조 및 개념을 포함하여 포괄적이고 정확한 정보를 제공합니다. 코드 예제를 사용하여 개념과 사용법을 설명합니다. 문서를 계속 업데이트하고, 변경 사항을 추적하고, 새로운 기능을 문서화하세요. GitHub 문제 및 포럼과 같은 지원 및 커뮤니티 리소스를 제공합니다. API 문서와 같은 실용적인 예제를 만듭니다.

Go 프레임워크 문서를 어떻게 사용하나요? 공식 웹사이트, GitHub 저장소, 타사 리소스 등 문서 유형을 결정합니다. 시작하기, 심층 튜토리얼, 참조 매뉴얼 등 문서 구조를 이해합니다. 필요에 따라 정보를 찾으십시오. 조직 구조 또는 검색 기능을 사용하십시오. 용어 및 개념 이해: 주의 깊게 읽고 새로운 용어와 개념을 이해합니다. 실제 사례: Beego를 사용하여 간단한 웹 서버를 만듭니다. 기타 Go 프레임워크 문서: Gin, Echo, Buffalo, Fiber.

애플리케이션 시나리오를 기반으로 최고의 Go 프레임워크를 선택하세요. 애플리케이션 유형, 언어 기능, 성능 요구 사항 및 생태계를 고려하세요. Common Go 프레임워크: Gin(웹 애플리케이션), Echo(웹 서비스), Fiber(높은 처리량), gorm(ORM), fasthttp(속도). 실제 사례: REST API(Fiber) 구축 및 데이터베이스(gorm)와 상호 작용. 프레임워크를 선택하세요. 주요 성능을 위해서는 fasthttp를 선택하고, 유연한 웹 애플리케이션을 위해서는 Gin/Echo를, 데이터베이스 상호작용을 위해서는 gorm을 선택하세요.
