如何使用 Visual C++(非 C++/CLI)处理 .mdb 数据库?
How to work with .mdb databases using Visual C++ (Not C++/CLI)?
我现在快疯了,因为我找不到解决以下任务的方法:
我想
- 从 MS Access .mdb 数据库中的 table 中读取数据
- 操纵所述数据并
- 将其写回同一个数据库
- 使用 Visual C++ 完成所有这些工作(而不是使用 CLI,因为我必须调整大量已经存在的代码)
为此,我尝试使用提供的解决方案 here,它使用 ADO 与 Northwind 2007.accdb 数据库一起工作(他们访问 .accdb 应该不是问题.mdb 对吗?)。我将那里给出的代码复制粘贴到 VS2017 x64 的一个空项目中,只调整了 Northwind 数据库的源路径并更改了以下行
hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
至
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
因为没有定义 hr。 (这是一个错误的调整吗?)
我安装了 MS Access 2016 64 位版本。
现在这是我的代码:
#import <C:\Program Files\Common Files\System\ado\msado15.dll> rename( "EOF", "AdoNSEOF" )
#include <iostream>
using namespace std;
int main() {
_bstr_t bstrConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Public\Downloads\Northwind 2007.accdb;";
// Shows the Data Access Method used in this sample.
const char* DAM = "ADO";
ADODB::_ConnectionPtr pConn("ADODB.Connection");
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
if (SUCCEEDED(hr)) {
cout << DAM << ": Successfully connected to database. Data source name:\n "
<< pConn->GetConnectionString() << endl;
// Prepare SQL query.
_bstr_t query = "SELECT Customers.[Company], Customers.[First Name] FROM Customers;";
cout << DAM << ": SQL query:\n " << query << endl;
// Excecute the query and create a record set.
ADODB::_RecordsetPtr pRS("ADODB.Recordset");
hr = pRS->Open(query,
_variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified,
ADODB::adLockUnspecified,
ADODB::adCmdText);
if (SUCCEEDED(hr)) {
cout << DAM << ": Retrieve schema info for the given result set: " << endl;
ADODB::Fields* pFields = NULL;
hr = pRS->get_Fields(&pFields);
if (SUCCEEDED(hr) && pFields && pFields->GetCount() > 0) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetName());
}
cout << endl;
} else {
cout << DAM << ": Error: Number of fields in the result set is 0." << endl;
}
cout << DAM << ": Fetch the actual data: " << endl;
int rowCount = 0;
while (!pRS->AdoNSEOF) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetValue());
}
cout << endl;
pRS->MoveNext();
rowCount++;
}
cout << DAM << ": Total Row Count: " << rowCount << endl;
}
pRS->Close();
pConn->Close();
cout << DAM << ": Cleanup. Done." << endl;
} else {
cout << DAM << ": Unable to connect to data source: " << bstrConnect << endl;
}
return 1;
}
代码编译通过,但在导入指令生成的msado15.tlh中显示了52个错误E0102(对于不同的行但总是相同的错误),描述为:枚举类型的前向声明不符合标准(粗略的翻译,我认为它明白了要点)。 (作为附带问题:使用导入指令时,我必须在项目属性的哪个位置 link msado15.dll 路径?我添加了 C:\Program Files\Common Files\System\ado Include 目录的路径,对吗?)
此外 运行 .exe 或在 Powershell 中执行它不起作用,Windows 发出消息“MYPROGRAM.exe 不是 运行 money”,只有关闭程序的选项。
我做错了什么?我是否选择了错误的方法来处理在我看来应该很容易解决的任务(在 Visual C++ 中读出该死的 table 应该不难)?
是否有更好的方法来使用 .mdb 数据库(例如使用 DAO、ODBC 或 OLE DB)以及是否有可以使用的最新代码示例或一个不错的 documentation/tutorial 逐步解释如何连接到数据库并显示如何读取和写入数据库?
EDIT1:A_Singh7 提供了以下解决方案:
- 将ghr定义为全局变量
- 将main函数的return值改为0
- 使用提供的代码 here
前两个解决方案没有成功,所以我尝试使用解决方案 3 中的代码。这是我收到的 Powershell 中的输出:
ADO: Successfully connected to database. Data source name:
Provider=Microsoft.ACE.OLEDB.12.0;User ID=admin;Data Source=C:\Users\Public\Downloads\Northwind 2007.accdb;Mode=Share Deny None;Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;Jet OLEDB:Bypass UserInfo Validation=False;Jet OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Validation=False;
ADO: SQL query
SELECT Customers.[Company], Customers.[First Name] FROM Customers;
之后,.exe 可悲地崩溃了,我仍然需要找出原因。尽管如此,建立与数据库的连接似乎可行,这是我遇到的主要问题。
尝试将 hr 声明为全局变量。
就像,
#include <iostream>
using namespace std;
HRESULT hr;
int main ()
{
// your code
// the line hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified); should remain as it is
}
先试试上面的方法,不行的话再换return1;到 return 0;.
如果这甚至不起作用,请看这里:
http://msdn.microsoft.com/en-us/library/cc811599.aspx
之后从这里寻求帮助:
Connecting to MS Access database using C++ using Visual Studio 2008
在这里,您只需要将文件 stafdx.h 作为 header 包含在内即可使代码完美运行。
我现在快疯了,因为我找不到解决以下任务的方法:
我想
- 从 MS Access .mdb 数据库中的 table 中读取数据
- 操纵所述数据并
- 将其写回同一个数据库
- 使用 Visual C++ 完成所有这些工作(而不是使用 CLI,因为我必须调整大量已经存在的代码)
为此,我尝试使用提供的解决方案 here,它使用 ADO 与 Northwind 2007.accdb 数据库一起工作(他们访问 .accdb 应该不是问题.mdb 对吗?)。我将那里给出的代码复制粘贴到 VS2017 x64 的一个空项目中,只调整了 Northwind 数据库的源路径并更改了以下行
hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
至
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
因为没有定义 hr。 (这是一个错误的调整吗?)
我安装了 MS Access 2016 64 位版本。
现在这是我的代码:
#import <C:\Program Files\Common Files\System\ado\msado15.dll> rename( "EOF", "AdoNSEOF" )
#include <iostream>
using namespace std;
int main() {
_bstr_t bstrConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Public\Downloads\Northwind 2007.accdb;";
// Shows the Data Access Method used in this sample.
const char* DAM = "ADO";
ADODB::_ConnectionPtr pConn("ADODB.Connection");
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
if (SUCCEEDED(hr)) {
cout << DAM << ": Successfully connected to database. Data source name:\n "
<< pConn->GetConnectionString() << endl;
// Prepare SQL query.
_bstr_t query = "SELECT Customers.[Company], Customers.[First Name] FROM Customers;";
cout << DAM << ": SQL query:\n " << query << endl;
// Excecute the query and create a record set.
ADODB::_RecordsetPtr pRS("ADODB.Recordset");
hr = pRS->Open(query,
_variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified,
ADODB::adLockUnspecified,
ADODB::adCmdText);
if (SUCCEEDED(hr)) {
cout << DAM << ": Retrieve schema info for the given result set: " << endl;
ADODB::Fields* pFields = NULL;
hr = pRS->get_Fields(&pFields);
if (SUCCEEDED(hr) && pFields && pFields->GetCount() > 0) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetName());
}
cout << endl;
} else {
cout << DAM << ": Error: Number of fields in the result set is 0." << endl;
}
cout << DAM << ": Fetch the actual data: " << endl;
int rowCount = 0;
while (!pRS->AdoNSEOF) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetValue());
}
cout << endl;
pRS->MoveNext();
rowCount++;
}
cout << DAM << ": Total Row Count: " << rowCount << endl;
}
pRS->Close();
pConn->Close();
cout << DAM << ": Cleanup. Done." << endl;
} else {
cout << DAM << ": Unable to connect to data source: " << bstrConnect << endl;
}
return 1;
}
代码编译通过,但在导入指令生成的msado15.tlh中显示了52个错误E0102(对于不同的行但总是相同的错误),描述为:枚举类型的前向声明不符合标准(粗略的翻译,我认为它明白了要点)。 (作为附带问题:使用导入指令时,我必须在项目属性的哪个位置 link msado15.dll 路径?我添加了 C:\Program Files\Common Files\System\ado Include 目录的路径,对吗?)
此外 运行 .exe 或在 Powershell 中执行它不起作用,Windows 发出消息“MYPROGRAM.exe 不是 运行 money”,只有关闭程序的选项。
我做错了什么?我是否选择了错误的方法来处理在我看来应该很容易解决的任务(在 Visual C++ 中读出该死的 table 应该不难)?
是否有更好的方法来使用 .mdb 数据库(例如使用 DAO、ODBC 或 OLE DB)以及是否有可以使用的最新代码示例或一个不错的 documentation/tutorial 逐步解释如何连接到数据库并显示如何读取和写入数据库?
EDIT1:A_Singh7 提供了以下解决方案:
- 将ghr定义为全局变量
- 将main函数的return值改为0
- 使用提供的代码 here
前两个解决方案没有成功,所以我尝试使用解决方案 3 中的代码。这是我收到的 Powershell 中的输出:
ADO: Successfully connected to database. Data source name:
Provider=Microsoft.ACE.OLEDB.12.0;User ID=admin;Data Source=C:\Users\Public\Downloads\Northwind 2007.accdb;Mode=Share Deny None;Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;Jet OLEDB:Bypass UserInfo Validation=False;Jet OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Validation=False;
ADO: SQL query
SELECT Customers.[Company], Customers.[First Name] FROM Customers;
之后,.exe 可悲地崩溃了,我仍然需要找出原因。尽管如此,建立与数据库的连接似乎可行,这是我遇到的主要问题。
尝试将 hr 声明为全局变量。 就像,
#include <iostream>
using namespace std;
HRESULT hr;
int main ()
{
// your code
// the line hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified); should remain as it is
}
先试试上面的方法,不行的话再换return1;到 return 0;. 如果这甚至不起作用,请看这里: http://msdn.microsoft.com/en-us/library/cc811599.aspx 之后从这里寻求帮助: Connecting to MS Access database using C++ using Visual Studio 2008 在这里,您只需要将文件 stafdx.h 作为 header 包含在内即可使代码完美运行。