MFC通过ADO连接数据库

来源:互联网 发布:photo域名 编辑:程序博客网 时间:2024/06/06 21:59

http://blog.chinaunix.net/uid-24585655-id-2125520.html 

MSDN中提供MFC的连接数据库的方法大约有三种方法一是CDatabase类(ODBC),一是DAO,另一是OLE DB,MSDN上推荐的方法是ODBC或者OLE DB方式。

   OLE DB是一组”组件对象模型”(COM) 接口,是新的数据库低层接口,它封装了ODBC的功能,并以统一的方式访问存储在不同信息源中的数据。OLE DB是Microsoft UDA(Universal Data Access)策略的技术基础。OLE DB 为任何数据源提供了高性能的访问,这些数据源包括关系和非关系数据库、电子邮件和文件系统、文本和图形、自定义业务对象等等。也就是说,OLE DB 并不局限于 ISAM、Jet 甚至关系数据源,它能够处理任何类型的数据,而不考虑它们的格式和存储方法。在实际应用中,这种多样性意味着可以访问驻留在 Excel 电子数据表、文本文件、电子邮件/目录服务甚至邮件服务器,诸如 Microsoft Exchange 中的数据。但是,OLE DB 应用程序编程接口的目的是为各种应用程序提供最佳的功能,它并不符合简单化的要求。您需要的API 应该是一座连接应用程序和OLE DB 的桥梁,这就是 ActiveX Data Objects (ADO)。
   使用ADO前必须在工程的stdafx.h头文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。
   ADO库是一组COM动态库,这意味应用程序在调用ADO前,必须初始化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的InitInstance成员函数里初始化OLE/COM库环境。
   然后ADO库包含三个基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口
   下面是编程步骤:
   1、在StdAfx.h加入:

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")

   2、初始化OLE/COM库,这个在应用程序类的InitInstance函数里面添加即可

if (!AfxOleInit())
    {
        AfxMessageBox("OLE init Error");
        return FALSE;
    }

我在网上看到还需要添加如下代码初始化com库

CoInitialize(NULL);//CoInitializeEx(NULL);

但是我并没有添加,却连接数据库成功,可能是和上面的初始化有相同的功能,或者AfxOleInit初始化时候调用了CoInitializeEx,不过如果在多线程下貌似需要在每个线程调用CoInitializeEx,等我后面用到了,在更新文章
   3、我只介绍我用到的接口,上面是初始化系统环境,下面声明一个接口

_ConnectionPtr pConn;

   4、打开链接

    const _bstr_t strSRC= "Driver={SQL Server};PROVIDER=SQLOLEDB;Data Source=SVCTAG-D76XZ2X;Database=bridge;Uid=test;Pwd=test;";
    if (FAILED(pConn.CreateInstance("ADODB.Connection")))
    {
        AfxMessageBox("Create Instance failed!");
        exit(0);
    }
    try{
        pConn->Open(strSRC,"","",-1);
    }
    catch (_com_error &e)
    {
        AfxMessageBox(e.Description());
        exit(0);
    }

    5、到此与数据库的连接顺利建立,下面就是执行sql语句,获取结果了

int CBridgeSql::execSql(CString sql)
{
    COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
    try
    {
        pConn->Execute(_bstr_t(sql),&vtOptional,adCmdText);
    }catch(_com_error &e){
        TRACE(sql);
        AfxMessageBox(e.Description());
        return -1;
    }
    return 0;
}

int CBridgeSql::execSql(CString sql,_RecordsetPtr &pRst)
{
    COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
    try
    {
        pRst=pConn->Execute(_bstr_t(sql),&vtOptional,adCmdText);
    }catch(_com_error &e){
        TRACE(sql);
        AfxMessageBox(e.Description());
        return -1;
    }
    return 0;
}

调用代码如下

_RecordsetPtr pRst(__uuidof(Recordset));
sql_cmd.Format("select * from bridge");
execSql(sql_cmd,pRst);
while(!pRst->adoEOF)
{
     pRst->GetCollect("bridge_id").intVal;
     CString temp;
     temp.Format((_bstr_t)pRst->GetCollect("name"));
}

其余两个接口有空再整理一下,上面问题,我会验证,待续