Beruflich Dokumente
Kultur Dokumente
C++ ADO
by Randy Charles Morin
I’m often asked for a HowTo tutorial on using ADO with C++. It is highly likely that I’ve
written more ADO with C++ than anybody on the planet. I often talk about how nice it is
to do database programming with ADO and C++. But this combination never made the
mainstream of programming.
Programming with ADO in C++ is just as easy as with Visual Basic, you just have to
explicitly release COM objects, handle exceptions and work with those nasty C++
pointers. But all in all, if you can handle the added complexity of C++, then you should
be able to create much more robust applications then with junior languages like Visual
Basic.
The best way to use ADO in C++ is to use the smart pointers created with the #import
directive in Visual C++.
#import "C:\Program files\Common Files\System\Ado\msado15.dll"
rename("EOF", "ADOEOF")
This eliminates the one of our concerns about C++, that is, explicitly releasing COM
objects. The smart pointers, if used correctly, should release the objects appropriately.
Let’s begin by creating a connection object.
ADODB::_ConnectionPtr connection;
hr = connection.CreateInstance(__uuidof(ADODB::Connection));
Ok, this looks about as easy as Visual Basic. Somethings wrong. This can’t be that
complex C++ stuff. I’m sure it’ll get harder later.
Let’s try opening a connection to our database.
connection->CursorLocation = ADODB::adUseClient;
connection->Open(L"Provider=sqloledb;Data Source=fifa;"
L"Initial Catalog=test;User Id=testsa;Password=testsa;", L"",
L"", ADODB::adConnectUnspecified);
Easy again. In fact, this all looks like the equivalent Visual Basic code, but using
pointers, namespaces and all those C++ thingys.
Now let’s create a table using SQL.
recordset->Open("CREATE TABLE mytable (value NVARCHAR(255))",
connection.GetInterfacePtr(), ADODB::adOpenForwardOnly,
ADODB::adLockReadOnly, ADODB::adCmdText);
I usually don’t to DDL (Data Definition Language) from ADO, but hell it’s easy.
while(!recordset->ADOEOF)
{
_variant_t var;
var = recordset->Fields->GetItem(L"value")->GetValue();
std::cout << static_cast<char *>(_bstr_t(var.bstrVal)) << std::endl;
recordset->MoveNext();
};
Actually selecting records is bit more difficult in C++, then in Visual Basic. The code to
get at the value is a nesting of pointers within pointers. This can be a little complex, but
really it’s easier than the naysayers had told us.
Finally, we close the recordset and DROP the table.
recordset->Close();
recordset->Open("DROP TABLE mytable", connection.GetInterfacePtr(),
ADODB::adOpenForwardOnly, ADODB::adLockReadOnly,
ADODB::adCmdText);
That was too easy. Who said ADO in C++ was all that difficult.
return buffer;
} ;
void main()
{
HRESULT hr;
CoInitialize(NULL);
try
{
ADODB::_ConnectionPtr connection;
hr = connection.CreateInstance(__uuidof(ADODB::Connection));
if (FAILED(hr))
{
throw _com_error(hr);
}
ADODB::_RecordsetPtr recordset;
hr = recordset.CreateInstance(__uuidof(ADODB::Recordset));
if (FAILED(hr))
{
throw _com_error(hr);
}
connection->CursorLocation = ADODB::adUseClient;
connection->Open(L"Provider=sqloledb;Data Source=fifa;"
L"Initial Catalog=test;User Id=testsa;Password=testsa;", L"",
L"", ADODB::adConnectUnspecified);
while(!recordset->ADOEOF)
{
_variant_t var;
var = recordset->Fields->GetItem(L"value")->GetValue();
std::cout << static_cast<char *>(_bstr_t(var.bstrVal))
<< std::endl;
recordset->MoveNext();
};
recordset->Close();
recordset->Open("DROP TABLE mytable", connection.GetInterfacePtr(),
ADODB::adOpenForwardOnly, ADODB::adLockReadOnly,
ADODB::adCmdText);
}
catch(_com_error &e)
{
std::cerr << ::outputashex(hr) << ":"
<< static_cast<char *>(e.Description());
}
catch(...)
{
std::cerr << "Unhandled Exception";
};
}