记录下ADO连接的详细步骤,方便以后忘记了回来查看。我用的环境:VS2017+Windows10+SQL Server。

1、引入ADO库:无需导入任何头文件,使用以下方法即可

// 说明:#import的这个路径,windows系统里面自带有ado的动态库。
//不同的操作系统可能msado15.dll这个库的名字不一样,这里以windows10为例,我这里是msado15.dll
#import "C:\Program Files\Common Files\System\ado\msado15.dll" named_guids \

// 重命名命名空间防止冲突
rename("EOF","adoEOF"),rename("BOF","adoBOF")

// 忽略警告
#pragma warning(default:4146)

// 使用命名空间
using namespace ADODB;

2、进行连接前需要对COM对象进行初始化

// 可以放到构造函数中
CoInitialize(NULL);

// 反初始化,一般放到析构函数中
CoUninitialize();

3、接下来可以进行连接了,有3个重要的对象,分别是:Connection(连接对象)、 Command(命令对象)、 Recordset(结果集对象)。ADO提供了相应的智能指针,我们使用的时候需要创建相应的变量(一般创建为成员变量)。

// 1、创建变量
_ConnectionPtr m_pConnection;  // 连接对象智能指针
_CommandPtr m_pCommand;  // 命令对象智能指针
_RecordsetPtr m_pRecordset;  // 结果集对象的智能指针

4、首先我们创建连接对象,然后进行连接。

if (nullptr == m_pConnection)
{
	try
	{
			if (!FAILED(m_pConnection.CreateInstance(__uuidof(Connection))))  // 创建对象
			{
				m_pConnection->CommandTimeout = 30;  // 设置超时时间 单位秒

				if (!FAILED(m_pConnection->Open((_bstr_t)m_szConnStr, “”, “”, adConnectUnspecified)))  // 连接
				{
					return true;
				}
			}
	}
	catch(_com_error e)
	{
			char szLog[1024] = { 0 };
			sprintf(szLog, "连接数据库错误:%s\n", e.Description());
			return false;
	}
}

说明:里面的Open函数中m_szConnStr为数据库连接串,如果不知道的话可以参考我另外写的一篇常用数据库的连接字符串:点击这里-数据库常用连接字符串 Open函数中的adConnectUnspecified为一个枚举值ConnectOptionEnum可选异步打开连接等

5、接下来需要对结果集对象进行初始化

if (nullptr == m_pRecordset)
	{
		try
		{
			if (!FAILED(m_pRecordset.CreateInstance(__uuidof(Recordset))))
			{
				return true;
			}
		}
		catch (_com_error e)
		{
			char szLog[1024] = { 0 };
			sprintf(szLog, "初始化结果集错误:%s\n", e.Description());
			return false;
		}

6、现在可以进行操作了(查询select,返回结果集的处理)

string SQL = "select * from emp";  // sql查询语句
long iRecordCount = 0;  // 保存结果集数量

m_pRecordset->Open((_variant_t)SQL.c_str(), m_pConnection.GetInterfacePtr(), adOpenStatic/*adOpenDynamic*/, adLockOptimistic, adCmdText);

iRecordCount = m_pRecordset->RecordCount;  // 获得结果集数量,可以用来判断是否查询有结果

if (iRecordCount < 1)
{
	return false;
}

获得结果后我们就可以取数据了,如果是MFC程序我们使用CString用来接收数据。

CString szTemp;
// 循环取结果,adoEOF是我们导入库的时候rename EOF的名字,用来判断是不是到结果集结束。
while(!m_pRecordset->adoEOF)
{
		// 使用CString接收结果字符串
		_variant_t var = m_pRecordset->GetCollect("ENAME");
		var.ChangeType(VT_BSTR);
		szTemp = var.bstrVal;

		std::cout << szTemp << std::endl;
		// 这个千万不能忘记,不然就是死循环
		m_pRecordset->MoveNext();
}

如果使用char *来接收字符串

char szTemp[1024] = { 0 };

// 循环取结果,adoEOF是我们导入库的时候rename EOF的名字,用来判断是不是到结果集结束。
while(!m_pRecordset->adoEOF)
{
		// 使用char*接收结果字符串
		_variant_t var = m_pRecordset->GetCollect("ENAME");
		// 将结果集宽字节转换成多字节
		WideCharToMultiByte(CP_ACP,0, var.bstrVal, -1, szTemp, sizeof(szTemp),NULL, NULL);
		std::cout << szTemp << std::endl;
		// 这个千万不能忘记,不然就是死循环
		m_pRecordset->MoveNext();
}

7、如果我们使用的sql语句不需要返回结果集,如update、insert等,此时我们可以直接使用connection执行

long RefreshNum = 0;  // 影响的行数
_variant_t varNum
string SQL = "update EMP set ename='Colin' where ename='SMITH'";

m_pConnection->Execute((_variant_t)SQL, &varNum, adCmdText);

RefreshNum = varNum.lVal;  // 获得受影响的行数