VC之ADO數據流存取
相信大家在開發項目時一般都會用到數據庫,以前開發web時,大部份的時間就是用代碼來處理數據,現在搞協同CAD系統的開發也要處理數據庫中的數據,(我的web和CAD是一個系統,協同嘛!)不同的是以前用C#,而現在要用c++,沒辦法,項目的第一步都是搞什麽密碼啊,權限管理之類的好,還有就是要存入文件什麽的!因為文件的數據量比較大,存取比其他類型的數據類型麻煩多了!
目標:用MFC(DLL)對Pro/E進行二次開發,對做好的模型(.prt文件)可以在服務器的數據庫中存取,我用的數據庫是SQL Server 2000
好先掛上我運行成功后的代碼:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void CPartToDBDlg::OnOK()
2 {
3 // TODO: Add extra validation here
4 ::CoInitialize(NULL);
5 //定义变量
6 _RecordsetPtr pRs=NULL;
7 _ConnectionPtr pConnection=NULL;
8 _variant_t varChunk;
9 HRESULT hr;
10 HLOCAL hMem;
11 BYTE* pbyte;
12 CString strHint;//提示信息
13 CFile strFileR;//定义读文件对象
14
15 LPTSTR pstrBack = _tcsrchr(m_sourcePath, '\\');//取得文件名称,只含文件名和最后一个'\'
16 strFileR.Open(m_sourcePath,CFile::modeRead);
17 long nLength=strFileR.GetLength();
18 hMem=LocalAlloc(LHND, nLength+1);//分配内存,将读出的数据放入其中
19 if (hMem == NULL)
20 {
21 return; //分配内存失败
22 }
23 pbyte=(BYTE*)LocalLock(hMem);// 锁定内存
24 memset(pbyte, (BYTE)0, strFileR.GetLength()+1);//初始化新分配的内存,设定初始值为0
25 strHint.Format("开始读取文件%s",m_sourcePath);//提示信息
26 AfxMessageBox(strHint);//读取文件到内存,注意这里是ReadHuge而非Read
27 strFileR.ReadHuge(pbyte,nLength);
28
29 BYTE* pBufEx;
30 pBufEx=pbyte;
31
32 SAFEARRAY* psa;
33 SAFEARRAYBOUND rgsabound[1];
34 rgsabound[0].lLbound=0;
35 rgsabound[0].cElements=nLength;
36 psa=SafeArrayCreate(VT_UI1,1,rgsabound);
37 for(long i=0;i<nLength;i++)
38 {
39 SafeArrayPutElement(psa,&i,pBufEx++);//Stores the data element at a given location in the array.
40 }
41 VARIANT varBLOB;
42 varBLOB.vt = VT_ARRAY | VT_UI1;
43 varBLOB.parray = psa;
44
45 _bstr_t strCnn("Provider=SQLOLEDB; Server=SEUHH\\SQLEXPRESS;Database=ProTkDB; uid=sa; pwd=;");
46 try
47 {
48 pConnection.CreateInstance(__uuidof(Connection)); //Open a connection
49 hr = pConnection->Open(strCnn,"","",NULL); //Connect a DataBase
50 pRs.CreateInstance(__uuidof(Recordset));
51 pRs->Open("select * from PartsClass where id=1",_variant_t((IDispatch*)pConnection,true),adOpenKeyset,adLockOptimistic,adCmdText); //Open a Table
52 pRs->Fields->GetItem("Image")->AppendChunk(varBLOB);
53 pRs->Update();
54 //給出提示信息顯示成功
55 CString sMsg;
56 sMsg.Format("數據字段長度為:%d",pRs->Fields->GetItem("Image")->ActualSize);
57 pRs->Close();
58 pConnection->Close();
59 AfxMessageBox(sMsg);
60 }
61 catch(_com_error &e)
62 {
63 // Notify the user of errors if any.
64 _bstr_t bstrSource(e.Source());
65 _bstr_t bstrDescription(e.Description());
66 CString sError;
67 sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
68 AfxMessageBox(sError);
69 }
70 //释放内存
71 LocalUnlock(pbyte);
72 LocalFree(hMem);
73 //关闭文件
74 strFileR.Close();
75 }
76
77 void CPartToDBDlg::OnCancel()
78 {
79 // TODO: Add extra cleanup here
80 // 2. VC把数据库中IMAGE字段取出存为文件
81 ::CoInitialize(NULL);
82 _RecordsetPtr pRs = NULL;
83 _ConnectionPtr pConnection = NULL;
84 HRESULT hr;
85 _bstr_t strCnn("Provider=SQLOLEDB; Server=SEUHH\\SQLEXPRESS;Database=ProTkDB; uid=sa; pwd=;");
86 try
87 {
88 pConnection.CreateInstance(__uuidof(Connection)); //Open a connection
89 hr = pConnection->Open(strCnn,"","",NULL); //Connect a DataBase
90 pRs.CreateInstance(__uuidof(Recordset));
91 pRs->Open("select * from PartsClass where id=1",_variant_t((IDispatch*)pConnection,true),adOpenKeyset,adLockOptimistic,adCmdText);
92 long lDataSize = pRs->GetFields()->GetItem("Image")->ActualSize;
93 char *m_pBuffer; //定义缓冲变量
94 if(lDataSize > 0)
95 {
96
97 _variant_t varBLOB;//从image字段中读取数据到varBLOB中
98 varBLOB = pRs->GetFields()->GetItem("Image")->GetChunk(lDataSize);
99 if(varBLOB.vt == (VT_ARRAY | VT_UI1))
100 {
101 if(m_pBuffer = new char[lDataSize+1]) //分配必要的存储空间
102 {
103 char *pBuf = NULL;
104 SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
105 memcpy(m_pBuffer,pBuf,lDataSize); ///复制数据到缓冲区m_pBuffer
106 SafeArrayUnaccessData (varBLOB.parray);
107 }
108 }
109 }
110 CFile file("d:\\user\\sweep_blend_5.prt",CFile::modeCreate|CFile::modeWrite);
111 file.Write(m_pBuffer,lDataSize);
112 file.Flush();
113 file.Close();
114 //給出提示信息顯示成功
115 CString sMsg;
116 sMsg.Format("數據字段長度為:%d",lDataSize);
117 pRs->Close();
118 pConnection->Close();
119 AfxMessageBox(sMsg);
120
121 }
122 catch(_com_error &e)
123 {
124 // Notify the user of errors if any.
125 _bstr_t bstrSource(e.Source());
126 _bstr_t bstrDescription(e.Description());
127 CString sError;
128 sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
129 AfxMessageBox(sError);
130 }
131
132 CDialog::OnCancel();
133 }
134
135 void CPartToDBDlg::OnButton1()
136 {
137 // TODO: Add your control notification handler code here
138 CString strFilter;
139 strFilter="All Files(*.*)|*.*||";
140 CFileDialog dlg(TRUE, NULL, NULL, OFN_EXPLORER|OFN_HIDEREADONLY|
141 OFN_ENABLESIZING|OFN_FILEMUSTEXIST,strFilter);
142
143 dlg.m_ofn.lStructSize = sizeof(OPENFILENAME);
144 if(dlg.DoModal() == IDOK )
145 {
146 m_sourcePath=dlg.GetPathName();//Edit控件
147 }
148 UpdateData(FALSE);
149 }
2 {
3 // TODO: Add extra validation here
4 ::CoInitialize(NULL);
5 //定义变量
6 _RecordsetPtr pRs=NULL;
7 _ConnectionPtr pConnection=NULL;
8 _variant_t varChunk;
9 HRESULT hr;
10 HLOCAL hMem;
11 BYTE* pbyte;
12 CString strHint;//提示信息
13 CFile strFileR;//定义读文件对象
14
15 LPTSTR pstrBack = _tcsrchr(m_sourcePath, '\\');//取得文件名称,只含文件名和最后一个'\'
16 strFileR.Open(m_sourcePath,CFile::modeRead);
17 long nLength=strFileR.GetLength();
18 hMem=LocalAlloc(LHND, nLength+1);//分配内存,将读出的数据放入其中
19 if (hMem == NULL)
20 {
21 return; //分配内存失败
22 }
23 pbyte=(BYTE*)LocalLock(hMem);// 锁定内存
24 memset(pbyte, (BYTE)0, strFileR.GetLength()+1);//初始化新分配的内存,设定初始值为0
25 strHint.Format("开始读取文件%s",m_sourcePath);//提示信息
26 AfxMessageBox(strHint);//读取文件到内存,注意这里是ReadHuge而非Read
27 strFileR.ReadHuge(pbyte,nLength);
28
29 BYTE* pBufEx;
30 pBufEx=pbyte;
31
32 SAFEARRAY* psa;
33 SAFEARRAYBOUND rgsabound[1];
34 rgsabound[0].lLbound=0;
35 rgsabound[0].cElements=nLength;
36 psa=SafeArrayCreate(VT_UI1,1,rgsabound);
37 for(long i=0;i<nLength;i++)
38 {
39 SafeArrayPutElement(psa,&i,pBufEx++);//Stores the data element at a given location in the array.
40 }
41 VARIANT varBLOB;
42 varBLOB.vt = VT_ARRAY | VT_UI1;
43 varBLOB.parray = psa;
44
45 _bstr_t strCnn("Provider=SQLOLEDB; Server=SEUHH\\SQLEXPRESS;Database=ProTkDB; uid=sa; pwd=;");
46 try
47 {
48 pConnection.CreateInstance(__uuidof(Connection)); //Open a connection
49 hr = pConnection->Open(strCnn,"","",NULL); //Connect a DataBase
50 pRs.CreateInstance(__uuidof(Recordset));
51 pRs->Open("select * from PartsClass where id=1",_variant_t((IDispatch*)pConnection,true),adOpenKeyset,adLockOptimistic,adCmdText); //Open a Table
52 pRs->Fields->GetItem("Image")->AppendChunk(varBLOB);
53 pRs->Update();
54 //給出提示信息顯示成功
55 CString sMsg;
56 sMsg.Format("數據字段長度為:%d",pRs->Fields->GetItem("Image")->ActualSize);
57 pRs->Close();
58 pConnection->Close();
59 AfxMessageBox(sMsg);
60 }
61 catch(_com_error &e)
62 {
63 // Notify the user of errors if any.
64 _bstr_t bstrSource(e.Source());
65 _bstr_t bstrDescription(e.Description());
66 CString sError;
67 sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
68 AfxMessageBox(sError);
69 }
70 //释放内存
71 LocalUnlock(pbyte);
72 LocalFree(hMem);
73 //关闭文件
74 strFileR.Close();
75 }
76
77 void CPartToDBDlg::OnCancel()
78 {
79 // TODO: Add extra cleanup here
80 // 2. VC把数据库中IMAGE字段取出存为文件
81 ::CoInitialize(NULL);
82 _RecordsetPtr pRs = NULL;
83 _ConnectionPtr pConnection = NULL;
84 HRESULT hr;
85 _bstr_t strCnn("Provider=SQLOLEDB; Server=SEUHH\\SQLEXPRESS;Database=ProTkDB; uid=sa; pwd=;");
86 try
87 {
88 pConnection.CreateInstance(__uuidof(Connection)); //Open a connection
89 hr = pConnection->Open(strCnn,"","",NULL); //Connect a DataBase
90 pRs.CreateInstance(__uuidof(Recordset));
91 pRs->Open("select * from PartsClass where id=1",_variant_t((IDispatch*)pConnection,true),adOpenKeyset,adLockOptimistic,adCmdText);
92 long lDataSize = pRs->GetFields()->GetItem("Image")->ActualSize;
93 char *m_pBuffer; //定义缓冲变量
94 if(lDataSize > 0)
95 {
96
97 _variant_t varBLOB;//从image字段中读取数据到varBLOB中
98 varBLOB = pRs->GetFields()->GetItem("Image")->GetChunk(lDataSize);
99 if(varBLOB.vt == (VT_ARRAY | VT_UI1))
100 {
101 if(m_pBuffer = new char[lDataSize+1]) //分配必要的存储空间
102 {
103 char *pBuf = NULL;
104 SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
105 memcpy(m_pBuffer,pBuf,lDataSize); ///复制数据到缓冲区m_pBuffer
106 SafeArrayUnaccessData (varBLOB.parray);
107 }
108 }
109 }
110 CFile file("d:\\user\\sweep_blend_5.prt",CFile::modeCreate|CFile::modeWrite);
111 file.Write(m_pBuffer,lDataSize);
112 file.Flush();
113 file.Close();
114 //給出提示信息顯示成功
115 CString sMsg;
116 sMsg.Format("數據字段長度為:%d",lDataSize);
117 pRs->Close();
118 pConnection->Close();
119 AfxMessageBox(sMsg);
120
121 }
122 catch(_com_error &e)
123 {
124 // Notify the user of errors if any.
125 _bstr_t bstrSource(e.Source());
126 _bstr_t bstrDescription(e.Description());
127 CString sError;
128 sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
129 AfxMessageBox(sError);
130 }
131
132 CDialog::OnCancel();
133 }
134
135 void CPartToDBDlg::OnButton1()
136 {
137 // TODO: Add your control notification handler code here
138 CString strFilter;
139 strFilter="All Files(*.*)|*.*||";
140 CFileDialog dlg(TRUE, NULL, NULL, OFN_EXPLORER|OFN_HIDEREADONLY|
141 OFN_ENABLESIZING|OFN_FILEMUSTEXIST,strFilter);
142
143 dlg.m_ofn.lStructSize = sizeof(OPENFILENAME);
144 if(dlg.DoModal() == IDOK )
145 {
146 m_sourcePath=dlg.GetPathName();//Edit控件
147 }
148 UpdateData(FALSE);
149 }
說明:
當然了,在工程中要先導入msado15.dll是必須的,其他的就看上面的代碼吧!在數據庫中對應的數據類型可以是image,text,ntext三種,我只對image的做了,
其他兩個沒做!還有就是這段程序是可以存取任何類型的文件數據的!
總結:
要注意做事的方法!我開始在網上找了很久都沒有找到,我想原因主要是因為我現在對VC,MFC還處於入門階段,很多函數都不認識,
上網看了很多,但就是達不到我的目的,畢竟代碼都是要完成個人所需的功能的,很是浪費時間,所以啊,還是應該從最簡單的功能做起,確定自己想要的東西,
多利用圖書館的資源,學校就是圖書館好,資源相當豐富,這個我是要肯定的…