Application of ADO Accessing database technology program in VC2011-05-16 11:48 440 People read comments (1) Favorites Reporting Database null SQL Server Access table DAO
One, database access technology
At present, database interface technology mainly has dao,rdo,odbc,ole DB and ADO
ODBC, developing database interconnection. Provides a unified interface for database development and can communicate with any database that has an ODBC driver. Compared with other database access technologies, it belongs to the database interface with lower base. You can only communicate with the care database, and you cannot access the non-relational database.
DAO, data Access object. Object-oriented database programming model based on COM. is a set of COM automation interfaces based on the Mircrosoft Access jet engine. Communicates directly with the Access/jet database and can communicate with other databases through the jet engine. Efficiency is not high. Originally a programming object for Visual Basic programmers as an abstraction of the ODBC API. Use the ODBC API to manipulate the data source. No need to go through a jet engine, which is more efficient than DAO.
OLE DB, an object link embedded in a database. Future database access development model. Provide COM interface, compared with other database access technology, it has better robustness and flexibility, higher fault tolerance. belong to the underlying access technology. You can communicate with relational and non-relational databases.
Ado,activex Data Object. High-level encapsulation of OLE DB. Simplifies OLE DB, which belongs to the high-level database interface. In addition, there are more programming languages that can use ADO than OLE DB. ADO provides an Automation interface that enables scripting languages such as VBScript and JavaScript to use ADO.
Second, ADO Access basics
1. Introducing the ADO type library
Use the following directive in Stdafx.h to introduce a type library:
#import "C:/Program Files/common files/system/ado/msado15.dll" no_namespace rename ("EOF", "adoeof")
Depending on the operating system, the Msado*.dll version is different, the current highest version is 2.1 bar. Rename ("EOF", "adoeof") is designed to prevent the same name from being marked with a different end.
In the compilation process, ignore the following compile warning:
Warning:unary minus operator applied to unsigned type, result still unsigned
If you do not want this warning to occur, you can include a line of code in the StdAfx.h file to prevent this warning: #pragma warning (disable:4146)
For the specified ADO version
If you use ADO 2.0 to add the following code
#import "C:/Program Files/common files/system/ole db/msdasc.dll" No_namespace
If you use ADO 2.1 to add the following code
#import "C:/Program Files/common files/system/ole db/oledb32.dll" No_namespace
Note: In ADO2.0 or ADO2.1, if one of the compilations is unsuccessful, use a different
2. Initializing a COM library
In general, initialize the COM library in the Application class initialization function, and of course it can be anywhere else. As long as it is initialized prior to use.
AfxOleInit (); Initializing a COM environment
Above is the MFC environment to register the COM method, if the non-MFC environment to use the following methods:
CoInitialize (NULL);
CoUninitialize ();
3. Create a Connection object and connect to the database
There are two main ways to link databases, static links and dynamic links.
Static Link:
_connectionptr m_pconnection;
Initializes it in the initialization function.
Try
{
hr = M_pconnection.createinstance ("ADODB.") Connection ");///Create Connection Object
if (SUCCEEDED (HR))
{
hr = M_pconnection->open ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb", "", "", adModeUnknown);///Connection Database
The Provider in the connection string in the above sentence is aimed at the ACCESS2000 environment, and for the ACCESS97, it needs to be changed to:P rovider=microsoft.jet.oledb.3.51;
}
}
catch (_com_error e)///catch exceptions
{
CString errormessage;
ErrorMessage. Format ("Connection database failure!/r/n error message:%s", E.errormessage ());
AfxMessageBox (errormessage);///Display error message
}
Suppose the database name is Test.mdb; The data source is test, and the following methods are used to connect to the database
Using ADO to connect to the ACCESS2000 database
M_pconnection->open ("Provider=mircrosoft.jet.oledb.4.0;data source=test.mdb", "" "," ", AdModeUnknown);
Using ADO to connect to the ACCESS97 database
M_pconnection->open ("Provider=mircrosoft.jet.oledb.3.51;data source=test.mdb", "" "," ", AdModeUnKnown);
To connect to any ODBC-enabled database using a DSN data source
M_pconnection->open ("Data source=test; Uid=sa; Pwd= "," "," "", adModeUnknown);
To connect to a SQL Server database without a data source
M_pconnection->open ("Driver={sql SERVER}"; Server=127.0.0.1;database=test; Uid=sa; Pwd= "," "," "", adModeUnknown);
Setting the database connection timeout requires calling before open
M_pconnection->connectiontimeout = 30;//sec
Dynamic Link:
HRESULT hr;
Idatasourcelocatorptr Dlprompt=null;
_RecordsetPtr Rs=null;
Try
{
Initializing the DataLinks object
Hr=dlprompt.createinstance (__uuidof (datalinks));
if (FAILED (HR))
Throw (_com_error (hr,null));
Establish a connection
Pconn=dlprompt->promptnew ();
If Conn is NULL
if (pconn==null)
Return
Open connection
Pconn->open (pconn->connectionstring,l "", L "",-1);
Clear list Box
while (M_tbllist.getcount () >0)
M_tbllist.deletestring (0);
Get the table set in the database
Rs=pconn->openschema (adSchemaTables);
while (!rs->adoeof)
{
M_tbllist.addstring ((char*) (_bstr_t) rs->fields->item[l "table_name"]->value);
Rs->movenext ();
}
Rs=null;
Dlprompt.release ();
}
catch (_com_error &e)
{
AfxMessageBox (E.errormessage ());
}
It should be noted that the Automation option is selected when the project is established. (see the specific situation)
Third, the data operation of ADO
1. Recordset object manipulation Data
The Recordset object is the simplest way to manipulate data, and is straightforward, especially if you are working directly with SQL statements. I am also the most common Recordset object.
_RecordsetPtr M_precordset;
M_precordset.createinstance ("ADODB.") Recordset ");
or write directly:
_RecordsetPtr precordset ("ADODB"). Recordset ");
You can also write this:
_RecordsetPtr precordset;
Precordset.createinstance (__uuidof (_recordset));
Note that if the variable is an instance of a class, it uses the "." operator, if a pointer to an instance should use the "->" operator.
A variable can be used in two ways. Because the "->" operator is overloaded, allowing an object instance to be used like an interface pointer, the "->" operator returns the pointer, and the returned pointer accesses the members of the _recordset object.
The following code to get all the records in the table to the Recordset object
CString strSQL = "SELECT * from student";
M_precordset->open (strsql,_variant_t (IDispatch *) m_pconnection,true), Adopenstatic,adlockoptimistic, adCmdText);
The first parameter is the SQL string to execute, and the second is the active connection
The third parameter is the cursor type. You can take the following values
Adopenunspecified = -1,///not specifically specified
adOpenForwardOnly = 0,///roll forward static cursor. This cursor can only navigate the recordset forward, such as scrolling forward with MoveNext, which improves browsing speed. But Recordcount,absoluteposition,absolutepage, like a bookmark, can't be used.
adOpenKeyset = 1,///A recordset with this cursor does not see the new or deleted actions of other users, but it is visible to you for updating the original record.
adOpenDynamic = 2,///dynamic cursor. All database operations are immediately reflected on each user record set.
adOpenStatic = 3///static cursor. It generates a static backup of your recordset, but other users ' additions, deletions, and updates are not visible to your recordset.
The fourth parameter, the lock type.
adlockunspecified = -1,///Not specified
adLockReadOnly = 1,///Read-only recordset
adLockPessimistic = 2, Pessimistic locking mode. Data locks all other actions when it is updated, which is the safest locking mechanism
adLockOptimistic = 3, Optimistic locking mode. The record is locked only when you call the Update method. Before this can still do the data update, INSERT, delete and other actions
adLockBatchOptimistic = 4, optimistic batch update. Records are not locked while editing, and changes, inserts, and deletions are done in batch mode.
A fifth parameter. Take one of the following values:
adCmdText: Indicates that CommandText is a text command
adCmdTable: Indicates that CommandText is a table name
Adcmdproc: Indicates that CommandText is a stored procedure
adCmdUnknown: Unknown
Gets the value of a field on a record
_variant_t vvalue = M_precordset->getcollect (_variant_t ((long) 0))///gets the 1th column value, counting from 0, you can also directly give the name of the row, as the next line
Vvalue = M_precordset->getcollect ("FieldName");///gets the value of the username field
Deletes a record that satisfies a condition. Move the cursor to the record you want to delete. Such as:
M_precordset->movefirst ();///move to the first record
M_precordset->delete (adaffectcurrent);///Delete current record
Add a record
M_precordset->addnew ();
M_precordset->putcollect ("ID", _variant_t ("value"));
M_precordset->updata ();
Modify Records
M_precordset->putcollect ("ID", _variant_t ("value"));
M_precordset->updata ();
2. Property
For each action in the class (or method, property call), there is a declaration to ensure that it can be called directly (or as the source form of the operation), and another declaration to invoke the source operation and throw a COM error when the operation fails. If the action is an attribute, the compilation indicator can create an interactive, VB-like syntax for the operation.
Returns/sets the operation of the property has a corresponding formal name-getproperty/putpropert, while setting a pointer to an ADO object property value is PutRefProperty. You will use the following form to read and write the value of the property:
variable = Objectptr->getproperty (); Reading the value of a property
Objectptr->putproperty (value); Set the value of a property
Objectptr->putrefproperty (&value); Sets the value of a pointer-type property
Using properties directly
__declspec (property ...) The compile indicator is a Microsoft-defined extension of the C language that makes a function work like a property. This way you can use the following syntax form to read and write the value of a property using vb: Objectptr->property = value; Set the value of a property
variable = objectptr->property; Reading the value of a property
__declspec (property ...) The compilation indicator can only be used for a property's read-write function and automatically generates the corresponding call form, depending on whether the property is available for reading or writing. Each property may have GetProperty, putproperty,putrefproperty three functions, but the compiler can only generate two forms of interaction. For example, the ActiveConnection property of a Command object has two read-write functions, Getactiveconnection and putrefactiveconnection. While the putref-form is a good choice in practice, you can save a pointer to an active connection object in this property. The Recordset object, on the other hand, has get-, put-, and putrefactiveconnection operations, but does not have an interactive syntactic form.
The
Collections,getitem method and Item properties
ADO defines several collection collection, including Fields,parameters,properties, and errors. In Visual C + +, the GetItem (index) method returns a member of the collection. Index is a Variant parameter that can be either a corresponding ordinal of that member or a string that includes its name.
__declspec (property ...) The compilation indicator generates a direct use form for the Item property corresponding to the GetItem () method (the interactive syntactic form mentioned above). This form is similar to using the syntax form of [] when referencing an array element:
Collectionptr->getitem (index);
Collectionptr->item[index];
for illustration, To assign a value to a field in RS of a Recordset object, this Recordset object is derived from the authors table in the pubs database. Use the item () property to access the third field in the Fields collection of this recordset (the collection is always numbered from 0, assuming the third field is named Au_fname). The value () method is then invoked to assign a string value to the field.
Rs->fields->getitem (2)->putvalue ("value");
Rs->fields->getitem ("au_fname")->putvalue ("value");
or:
Rs->fields->item[2]->value = "value";
rs->fields->item["au_fname"]->value = "value ";
3. com-specific data types
The data types that are used exclusively for COM are: Variant, BSTR, and SafeArray.
Variant
A variant is a structured data type that contains a representation of a member value and its data type. A variant can represent quite a number of data types, or even another variant, BSTR, Boolean, IDispatch or IUnknown pointer, currency, date, and so on. COM also provides a number of ways to make conversion between data types more simplistic.
The _variant_t class encapsulates and manages a variant of this data type.
When a method or property of ADO uses a parameter, it usually means that a parameter of type _variant_t is required. As an exception, it is sometimes required that the operand be a standard data type, such as long or byte, or an enumeration value. Another exception is the requirement that the operand be a string of strings.
BSTR
BSTR (Basic string) is also a structured data type, including the length of strings and strings. COM provides a way to allocate, manipulate, and release strings of space.
The _bstr_t class encapsulates and manages the BSTR data type.
When a method or property uses a string parameter, it usually means that a class-_bstr_t parameter is required.
Forced type conversions for _variant_t and _bstr_t classes
Typically, you do not need an explicit type conversion code when passing a _variant_t or _bstr_t parameter to an operation. If the _variant_t or _bstr_t class provides a constructor that corresponds to the parameter type, the compiler will automatically generate the appropriate _variant_t or _bstr_t values.
However, when the arguments are ambiguous, when multiple constructors are corresponding, you must explicitly call the correct constructor to get the correct arguments. For example, the function declaration of the Recordset::Open method is as follows:
HRESULT Open (
Const _VARIANT_T & Source,
Const _variant_t & ActiveConnection,
Enum CursorTypeEnum CursorType,
Enum LockTypeEnum LockType,
Long Options);
Where the parameter ActiveConnection is a reference to a variant_t variable, it can be a connection string or a pointer to an open connection object.
The correct _variant_t type parameter will be constructed regardless of whether you are passing a similar "dsn=pubs;uid=sa;pwd=;" Such a string, or a pointer similar to "(IDispatch *) Pconn". Alternatively, you can explicitly write code such as "_variant_t (IDispatch *) Pconn, True)" to pass a _variant_t variable that contains pointers. The coercion type conversion (IDispatch *) Here avoids the ambiguity of the possible invocation of the IUnknown interface constructor. Although it is rarely mentioned, it is particularly important that ADO is always a IDispatch interface. Any pointer that is passed in the contained variant must be converted to a IDispatch interface pointer.
The last thing to note is that the second logical parameter of the constructor is optional, and its default value is true. This parameter determines whether the variant constructor calls the inline AddRef () method and whether the _variant_t::release () method is automatically invoked after the ADO method or property call is completed
SafeArray
SafeArray is also a structured data type that consists of an array of data elements of other data types. It is called a secure array because it contains the boundary information for each dimension and restricts access to the array elements within the bounds.
When a method or property is to use or return an array, it usually means a SAFEARRAY array, rather than a localized c/C + + array.
For example, the second parameter of the connection object's OpenSchema method requires an array of variant values. These variant values must be passed as elements of a SAFEARRAY array. And the SAFEARRAY array itself is passed as a variant.
Further, the first parameter of the Find method is an optional first and second parameter of the Variant;addnew method that points to a one-dimensional SAFEARRAY array, also a one-dimensional SAFEARRAY array The return value of the GetRows method is a variant that contains a two-D SAFEARRAY array.
The following code demonstrates how to use a SAFEARRAY array using a _variant_t. Note that the annotation corresponds to the encoding step.
1. Again, the TESTHR () built-in function is defined to take advantage of the stored error handling mechanism.
2. If you only need a one-dimensional array, you can use Safearraycreatevector instead of safearraybound declarations and safearraycreate functions. The following code uses the SafeArrayCreate:
Safearraybound sabound[1];
Sabound[0].llbound = 0;
Sabound[0].celements = 4;
PSa = SafeArrayCreate (vt_variant, 1, sabound);
3. Enumeration constants adSchemaColumns The defined pattern, which is associated with TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, and column_name four columns. To do this, an array with four variant elements is created. The values corresponding to the third column table_name are set.
The returned recordset, consisting of several columns, is only a subset of the corresponding columns, and the values for each row are maintained at one by one correspondence.
4. People who are familiar with SAFEARRAYs may be surprised to not invoke SafeArrayDestroy () before exiting. In fact, invoking SafeArrayDestroy () in this case can cause a Run-time exception to occur. This is because the Vtcriteria destructor calls VariantClear () when _variant_t is out of use, releasing SafeArray. Invoking only SafeArrayDestroy without manually clearing the _variant_t will cause the destructor to attempt to clear an invalid SAFEARRAY pointer. If you want to invoke SafeArrayDestroy (), then the code should look like this:
Testhr (SafeArrayDestroy (pSa));
VTCRITERIA.VT = Vt_empty;
Vtcriteria.parray = NULL;
It's actually more like letting _variant_t manage SAFEARRAY.
The complete code is as follows:
#import "C:/Program Files/common files/system/ado/msado15.dll"/
No_namespace rename ("EOF", "Endoffile")
#include
Note 1
inline void Testhr (HRESULT _hr)
{if FAILED (_hr) _com_issue_error (_hr);}
void Main (void)
{
CoInitialize (NULL);
Try
{
_RecordsetPtr pRs ("ADODB"). Recordset ");
_connectionptr pCn ("ADODB"). Connection ");
_variant_t vttablename ("authors"),
Vtcriteria;
Long ix[1];
SAFEARRAY *PSA = NULL;
Pcn->open ("dsn=pubs; User id=sa;pwd=; Provider=msdasql; "," "," ",
adconnectunspecified);
Note 2, note 3
PSa = Safearraycreatevector (vt_variant, 1, 4);
if (!PSA) _com_issue_error (e_outofmemory);
Assigns a value table_name to the third element (index value 2).
Ix[0] = 2;
Testhr (SafeArrayPutElement (PSa, IX, &vttablename));
Because the variant does not have a SafeArray constructor, the data type and value of the variant are set manually.
VTCRITERIA.VT = Vt_array | Vt_variant;
Vtcriteria.parray = PSa;
PRs = Pcn->openschema (adSchemaColumns, Vtcriteria, vtmissing);
Long limit = Prs->getfields ()->count;
for (long x = 0; x < limit x + +)
printf ("%d:%s/n", x+1,
; ((char*) prs->getfields ()->item[x]->name));
//Note 4
prs->close ()
pcn->close ();
}
CA TCH (_com_error &e)
{
printf ("error:/n");
printf ("Code =%08lx/n" , E.error ());
printf ("Code meaning =%s/n", (char*) e.errormessage ());
printf ("Source =%s/n", (char*) E.source ());
printf ("Description =%s/n", (char*) e.description ());
}
couninitialize ();
}
using (IDispatch *) to convert pointer types of ADO objects
1. Encapsulates an active connection object explicitly in a variant and then uses (IDispatch *) for type conversion to ensure that the correct constructor is invoked. Also explicitly sets the second argument to the default true, so that the reference count of the object is properly maintained after the Recordset::Open operation completes.
2. An expression (_bstr_t) is not a type conversion, but rather a _variant_t operator from which to extract a _bstr_t string.
An expression (char*) is not a type conversion, but rather a _bstr_t operator from which to extract a pointer to a string encapsulated in _bstr_t.
The following code demonstrates some of the common operations of _variant_t and _bstr_t.
#import "C:/Program Files/common files/system/ado/msado15.dll"/
No_namespace rename ("EOF", "Endoffile")
#include
void Main (void)
{
CoInitialize (NULL);
Try
{
_connectionptr pconn ("ADODB"). Connection ");
_RecordsetPtr PRST ("ADODB"). Recordset ");
Pconn->open ("Provider=sqloledb;data source=a-tima10;")
"Initial catalog=pubs; User Id=sa; password=; ",
"", "", adconnectunspecified);
Note 1
Prst->open (
"Authors",
_variant_t ((IDispatch *) Pconn, True),
adOpenStatic,
adLockReadOnly,
adCmdTable);
Prst->movelast ();
NOTE 2
printf ("Last name is '%s '%s '),"
(char*) ((_bstr_t) Prst->getfields ()->getitem ("au_fname")->getvalue ()),
(char*) ((_bstr_t) prst->fields->item["au_lname"]->value));
Prst->close ();
Pconn->close ();
}
catch (_com_error &e)
{
printf ("Description = '%s '/n", (char*) e.description ());
}
:: CoUninitialize ();
}