Sei sulla pagina 1di 4

www.kbcafe.

com March 23, 2002

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, that was easy.


Now let’s create a recordset object.
ADODB::_RecordsetPtr recordset;
hr = recordset.CreateInstance(__uuidof(ADODB::Recordset));

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.

Copyright 2002-2003 Randy Charles Morin


www.kbcafe.com March 23, 2002

And inserting a record?


recordset->Open("INSERT INTO mytable VALUES ('Hello')",
connection.GetInterfacePtr(), ADODB::adOpenForwardOnly,
ADODB::adLockReadOnly, ADODB::adCmdText);
recordset->Open("INSERT INTO mytable VALUES ('Goodbye')",
connection.GetInterfacePtr(), ADODB::adOpenForwardOnly,
ADODB::adLockReadOnly, ADODB::adCmdText);

Cake. In fact, I insert two records.


I guess selecting records is easy too?
recordset->Open("SELECT * from mytable", connection.GetInterfacePtr(),
ADODB::adOpenForwardOnly, ADODB::adLockReadOnly, ADODB::adCmdText);

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.

About the Author


Randy Charles Morin is the Chief Architect of SportMarkets Development from Toronto,
Canada and lives with his wife, Bernadette and two kids, Adelaine and Brayden in
Brampton, Canada. He is the author of the KBCafe.com website
[http://www.kbcafe.com], many programming books and many articles.
The full listing of code wrapped into a console application follows.
Listing 1: ADO Listing
#include <iostream>
#include <string>

#import "C:\Program files\Common Files\System\Ado\msado15.dll"


rename("EOF", "ADOEOF")

std::string outputashex(unsigned long l)


{
char buffer[1024];
::itoa(l, buffer, 16);

Copyright 2002-2003 Randy Charles Morin


www.kbcafe.com March 23, 2002

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);

recordset->Open("CREATE TABLE mytable (value NVARCHAR(255))",


connection.GetInterfacePtr(), ADODB::adOpenForwardOnly,
ADODB::adLockReadOnly, ADODB::adCmdText);

recordset->Open("INSERT INTO mytable VALUES ('Hello')",


connection.GetInterfacePtr(), ADODB::adOpenForwardOnly,
ADODB::adLockReadOnly, ADODB::adCmdText);
recordset->Open("INSERT INTO mytable VALUES ('Goodbye')",
connection.GetInterfacePtr(), ADODB::adOpenForwardOnly,
ADODB::adLockReadOnly, ADODB::adCmdText);

recordset->Open("SELECT * from mytable",


connection.GetInterfacePtr(),
ADODB::adOpenForwardOnly, ADODB::adLockReadOnly,
ADODB::adCmdText);

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(),

Copyright 2002-2003 Randy Charles Morin


www.kbcafe.com March 23, 2002

ADODB::adOpenForwardOnly, ADODB::adLockReadOnly,
ADODB::adCmdText);
}
catch(_com_error &e)
{
std::cerr << ::outputashex(hr) << ":"
<< static_cast<char *>(e.Description());
}
catch(...)
{
std::cerr << "Unhandled Exception";
};
}

Copyright 2002-2003 Randy Charles Morin

Potrebbero piacerti anche