目录
预备阅读
步骤
总结
首页 数据库 mysql教程 结合ADO、ADOX和MFC的文档/视图/框架架构创建和打开Access数据库

结合ADO、ADOX和MFC的文档/视图/框架架构创建和打开Access数据库

Jun 07, 2016 pm 03:39 PM
mfc 建和 文档 架构 框架 结合 视图

本文描述了如何在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

步骤

  1. 在计算机上安装MDAC2.5以上版本
  2. 打开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的安装路径,这里的路径可能有所不同。
  3. 在文档类中声明数据库连接 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;
    }
  4. 编写一个辅助函数,用于创建数据库、表和索引
    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   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     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;
    }
  5. 辅助的数据库函数。由于这些函数是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;
    }
  6. 错误处理代码
    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++可以作为参考。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

golang框架架构的学习曲线有多陡峭? golang框架架构的学习曲线有多陡峭? Jun 05, 2024 pm 06:59 PM

Go框架架构的学习曲线取决于对Go语言和后端开发的熟悉程度以及所选框架的复杂性:对Go语言的基础知识有较好的理解。具有后端开发经验会有所帮助。复杂性不同的框架导致学习曲线差异。

如何评估Java框架商业支持的性价比 如何评估Java框架商业支持的性价比 Jun 05, 2024 pm 05:25 PM

评估Java框架商业支持的性价比涉及以下步骤:确定所需的保障级别和服务水平协议(SLA)保证。研究支持团队的经验和专业知识。考虑附加服务,如升级、故障排除和性能优化。权衡商业支持成本与风险缓解和提高效率。

综述!全面概括基础模型对于推动自动驾驶的重要作用 综述!全面概括基础模型对于推动自动驾驶的重要作用 Jun 11, 2024 pm 05:29 PM

写在前面&笔者的个人理解最近来,随着深度学习技术的发展和突破,大规模的基础模型(FoundationModels)在自然语言处理和计算机视觉领域取得了显着性的成果。基础模型在自动驾驶当中的应用也有很大的发展前景,可以提高对于场景的理解和推理。通过对丰富的语言和视觉数据进行预训练,基础模型可以理解和解释自动驾驶场景中的各类元素并进行推理,为驾驶决策和规划提供语言和动作命令。基础模型可以根据对驾驶场景的理解来实现数据增强,用于提供在常规驾驶和数据收集期间不太可能遇到的长尾分布中那些罕见的可行

PHP 框架的学习曲线与其他语言框架相比如何? PHP 框架的学习曲线与其他语言框架相比如何? Jun 06, 2024 pm 12:41 PM

PHP框架的学习曲线取决于语言熟练度、框架复杂性、文档质量和社区支持。与Python框架相比,PHP框架的学习曲线更高,而与Ruby框架相比,则较低。与Java框架相比,PHP框架的学习曲线中等,但入门时间较短。

PHP 框架的轻量级选项如何影响应用程序性能? PHP 框架的轻量级选项如何影响应用程序性能? Jun 06, 2024 am 10:53 AM

轻量级PHP框架通过小体积和低资源消耗提升应用程序性能。其特点包括:体积小,启动快,内存占用低提升响应速度和吞吐量,降低资源消耗实战案例:SlimFramework创建RESTAPI,仅500KB,高响应性、高吞吐量

golang框架文档最佳实践 golang框架文档最佳实践 Jun 04, 2024 pm 05:00 PM

编写清晰全面的文档对于Golang框架至关重要。最佳实践包括:遵循既定文档风格,例如Google的Go编码风格指南。使用清晰的组织结构,包括标题、子标题和列表,并提供导航。提供全面准确的信息,包括入门指南、API参考和概念。使用代码示例说明概念和使用方法。保持文档更新,跟踪更改并记录新功能。提供支持和社区资源,例如GitHub问题和论坛。创建实际案例,如API文档。

如何为不同的应用场景选择最佳的golang框架 如何为不同的应用场景选择最佳的golang框架 Jun 05, 2024 pm 04:05 PM

根据应用场景选择最佳Go框架:考虑应用类型、语言特性、性能需求、生态系统。常见Go框架:Gin(Web应用)、Echo(Web服务)、Fiber(高吞吐量)、gorm(ORM)、fasthttp(速度)。实战案例:构建RESTAPI(Fiber),与数据库交互(gorm)。选择框架:性能关键选fasthttp,灵活Web应用选Gin/Echo,数据库交互选gorm。

golang框架文档使用说明 golang框架文档使用说明 Jun 05, 2024 pm 06:04 PM

如何使用Go框架文档?确定文档类型:官网、GitHub存储库、第三方资源。了解文档结构:入门指南、深入教程、参考手册。根据需要定位信息:使用组织结构或搜索功能。理解术语和概念:仔细阅读并理解新的术语和概念。实战案例:使用Beego创建一个简单的Web服务器。其他Go框架文档:Gin、Echo、Buffalo、Fiber。

See all articles