VC++通过ADO连接数据库(一)

有关数据库的开发做的很少,以前都只是算法类的程序编写,现在对在VC++中连接sqlserver数据库的方法做个总结,以备以后查阅


首先,在stdafx.h头文件中添加以下语句
#import "C:\ProgramFiles\CommonFiles\System\ado\msado15.dll"no_namespacerename("EOF","adoEOF")
导入ado库,no_namespace表示无命名空间,rename("EOF","adoEOF")表示重命名eof  为 adoefo  避免和其他的常量冲突

接着,在MFC中可以用AfxOleInit();非MFC环境中用:
CoInitialize(NULL);
CoUnInitialize();

一般MFC程序中都是默认初始化Com口的。


然后,创建ADO连接数据库的智能指针,下面将分别讲述如何利用_ConnectionPtr和_CommandPtr以及_RecordsetPtr连接数据库的方法

1.利用_ConnectionPtr连接和操作数据库

_ConnectionPtr pConnectionPtr;
	//连接字串,连接Sqlserver
	CString strConnection = "Provider=SQLOLEDB;Persist Security Info=False;Integrated Security=SSPI;Initial Catalog=ImageDB;Data Source=.\\SQLEXPRESS";
	pConnectionPtr.CreateInstance("ADODB.Connection");
	HRESULT hr=pConnectionPtr->Open(_bstr_t(strConnection),"","",adConnectUnspecified);
	if (FAILED(hr))
	{
		pConnectionPtr.Release();
		return;
	}
	CString strSql = "insert into StudentInfo values('wang',22,'boy')";
	COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
	pConnectionPtr->Execute(_bstr_t(strSql),vtOptional,-1);
	pConnectionPtr->Close();
	pConnectionPtr.Release();


_ConnectionPtr返回一个记录集或空指针,通常使用它来创建数据库连接和执行一条不返回任何结果的SQL语句,如一个存储过程。使用_ConnectionPtr返回一个记录集不是一个好的使用方法,对于要返回记录的操作,通常用_RecordsetPtr来实现,使用_ConnectionPtr来操作时想要得到记录的条数得遍历所有的记录,而用_RecordsetPtr时不需要

2.利用_CommandPtr来连接和操作数据库

_CommandPtr pCommandPtr;
	pCommandPtr.CreateInstance("ADODB.Command");
	pCommandPtr->ActiveConnection = pConnectionPtr;
	pCommandPtr->CommandText = "insert into StudentInfo values('wang',22,'boy')";
	pCommandPtr->Execute(NULL,NULL,adCmdText);
	pCommandPtr->CommandText = "select * from StudentInfo";
	_RecordsetPtr pRecordsetPtr = pCommandPtr->Execute(NULL,NULL,adCmdText);
	_variant_t vName = pRecordsetPtr->GetCollect((_variant_t)(long)0);//取得第一个字段
	CString sName = (LPCTSTR)_bstr_t(vName);
	pCommandPtr.Release();
	pRecordsetPtr->Close();
_CommandPtr返回一个记录集。

它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。

在使用_CommandPtr接口时,你可以使用全局的_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接字串。

如果你执行一次或几次数据库操作,使用连接字串是比较好的选择。

如果你要频繁访问数据库,并返回很多记录集,那么使用全局的_ConnectionPtr是个比较好的选择。

3.利用_RecordsetPtr连接和操作数据库

_RecordsetPtr pRecordsetPtr;
	pRecordsetPtr.CreateInstance("ADODB.Recordset");
	CString strConnection = "Provider=SQLOLEDB;Persist Security Info=False;Integrated Security=SSPI;Initial Catalog=ImageDB;Data Source=.\\SQLEXPRESS";
	CString strSQL = "select name,age,sex from StudentInfo";
	if (FAILED(pRecordsetPtr->Open(_variant_t(strSQL),_variant_t(strConnection),adOpenStatic,adLockOptimistic,adCmdText)))
	{
		pRecordsetPtr->Close();
		return FALSE;
	}
	while(!pRecordsetPtr->GetadoEOF())
	{
		_variant_t VarName;
		_variant_t VarAge;
		_variant_t VarSex;

		VarName = pRecordsetPtr->GetCollect("Name");
		VarAge = pRecordsetPtr->GetCollect("Age");
		VarSex = pRecordsetPtr->GetCollect("Sex");

		CString sName = (char *)_bstr_t(VarName);
		CString sAge  = (char *)_bstr_t(VarAge);
		CString sSex  = (char *)_bstr_t(VarSex);

		pRecordsetPtr->MoveNext();
	}
	pRecordsetPtr->Close();
	pRecordsetPtr.Release();

与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定,游标控制等。
同_CommandPtr接口一样,它不一定要使用一个已经创建的数据连接,
可以用一个连接串代替连接指针赋给_RecordsetPtr的connection成员变量,
让它自己创建数据连接。
如果你要使用多个记录集,
最好的方法是同Command对象一样使用已经创建了数据连接的全局_ConnectionPtr接口,
然后使用_RecordsetPtr执行存储过程和SQL语句。

下面给出一个完整点的例子,作用是保存本地的bmp图片到数据库中

CFile file;
	int iLen;
	if( !file.Open( "Test.bmp", CFile::modeRead) )
		return ;
	iLen = (DWORD)file.GetLength();
	char* pBMPContent = new char[iLen + 1];
	if(!pBMPContent)
		return ;
	if(file.Read(pBMPContent,iLen) != iLen)
		return ;
	//保存到数据库
	_ConnectionPtr pConnectionPtr;
	_RecordsetPtr pRecordsetPtr;
	_CommandPtr pCommandPtr;
	try
	{
		CString strConnection = "Provider=SQLOLEDB;Persist Security Info=False;Integrated Security=SSPI;Initial Catalog=ImageDB;Data Source=.\\SQLEXPRESS";
		pConnectionPtr.CreateInstance("ADODB.Connection");
		pConnectionPtr->Open(_bstr_t(strConnection),"","",adConnectUnspecified);
		pRecordsetPtr.CreateInstance(__uuidof(Recordset));
		//+--------------------------------------------------------------+
		//+ 利用Command执行SQL语句,判断当前项目是否已存在图,若存在则删除
		//+ 在项目中修改图时会出现这种情况
		char *lpszRetValue = (char *)malloc(sizeof(char)*255);
		pCommandPtr.CreateInstance(__uuidof(Command));
		pCommandPtr->CommandTimeout = 30;
		pCommandPtr->ActiveConnection = pConnectionPtr;
		sprintf_s(lpszRetValue,254,"select Count(*) RstCount from ImageTable where ProjectName = '%s' and ExperimentName = '%s'",m_sProjectName,m_sExperimentName);
		pCommandPtr->CommandText = lpszRetValue;
		pRecordsetPtr = pCommandPtr->Execute(NULL,NULL,adCmdText);
		_variant_t vtValue;
		vtValue = pRecordsetPtr->GetCollect("RstCount");
		if (NULL != vtValue.vt)
		{
			strncpy((char*)lpszRetValue,LPCSTR(_bstr_t(vtValue)),255);
		}
		int iRstCount = atoi(lpszRetValue);
		free(lpszRetValue);
		if (iRstCount != 0)
		{
			sprintf_s(lpszRetValue,254,"delete from ImageTable where ProjectName = '%s' and ExperimentName = '%s'",m_sProjectName,m_sExperimentName);
			pCommandPtr->CommandText = lpszRetValue;
			pCommandPtr->Execute(NULL,NULL,adCmdText);
		}
		pRecordsetPtr->Close();
		//+--------------------------------------------------------------+
		HRESULT hr = pRecordsetPtr->Open("select * from ImageTable",_variant_t(pConnectionPtr,true),adOpenDynamic,adLockPessimistic,adCmdText);
		pRecordsetPtr->AddNew();

		SYSTEMTIME st;
		CString sSaveTime;
		GetLocalTime(&st);
		sSaveTime.Format("%4d-%02d-%02d %02d:%02d:%02d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);

		pRecordsetPtr->PutCollect("SaveTime",_variant_t(sSaveTime));
		pRecordsetPtr->PutCollect("ProjectName",_variant_t(m_sProjectName));
		pRecordsetPtr->PutCollect("ExperimentName",_variant_t(m_sExperimentName));
		VARIANT varBLOB;
		SAFEARRAY *psa;
		SAFEARRAYBOUND rgsabound[1];
		rgsabound->lLbound = 0;
		rgsabound->cElements = iLen;
		psa = SafeArrayCreate(VT_UI1,1,rgsabound);
		for (long i=0;i<(long)iLen;i++)
		{
			SafeArrayPutElement (psa, &i, pBMPContent++);
		}
		varBLOB.vt = VT_ARRAY | VT_UI1;
		varBLOB.parray = psa;
		pRecordsetPtr->GetFields()->GetItem("Information")->AppendChunk(varBLOB);
		pRecordsetPtr->Update();
	}
	catch (_com_error  e)
	{
		dump_com_error(e);
	}
	if (pConnectionPtr->State)
	{
		pConnectionPtr->Close();
		pConnectionPtr.Release();
	}
	if (pRecordsetPtr->State)
	{
		pRecordsetPtr->Close();
		pRecordsetPtr = NULL;
	}


你可能感兴趣的:(C++,数据库,Visual)