有关数据库的开发做的很少,以前都只是算法类的程序编写,现在对在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();
下面给出一个完整点的例子,作用是保存本地的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; }