Freigeben über


Visual C++ ADO-Programmierung

Gilt für: Access 2013, Office 2013

In der ADO-API-Referenz wird die Funktionalität der ADO-Anwendungsprogrammierschnittstelle (Application Programming Interface, API) mit einer Microsoft Visual Basic ähnlichen Syntax beschrieben. Diese Referenz richtet sich an alle Benutzer, aber ADO-Programmierer (ActiveX Data Objects) setzen verschiedene Sprachen wie Visual Basic, Visual C++ (mit und ohne die #import -Direktive) und Visual J++ (mit dem ADO/WFC-Klassenpaket) ein.

Um dieser Vielfalt gerecht zu werden, bieten die ADO für Visual C++-Syntaxindizes eine Visual C++-sprachspezifische Syntax mit Verknüpfungen zu allgemeinen Beschreibungen der Funktionalität, der Parameter, außergewöhnlichen Verhaltensweisen usw. in der API-Referenz.

ADO wird mit COM-Schnittstellen (Component Object Model) implementiert. In bestimmten Programmiersprachen ist es jedoch einfacher für Programmierer mit COM zu arbeiten als in anderen. Beispielsweise werden nahezu alle Details der Verwendung von COM implizit für Visual Basic-Programmierer behandelt, wohingegen Visual C++-Programmierer die Details selbst ermitteln müssen.

The following sections summarize details for C and C++ programmers using ADO and the #import directive. Der Schwerpunkt liegt auf datentypspezifischen Datentypen für COM (Variant, BSTR und SafeArray) und Fehlerbehandlung (_com_error).

Verwenden der #import Compilerdirektive

The #import Visual C++ compiler directive simplifies working with the ADO methods and properties. The directive takes the name of a file containing a type library, such as the ADO .dll (Msado15.dll), and generates header files containing typedef declarations, smart pointers for interfaces, and enumerated constants. Each interface is encapsulated, or wrapped, in a class.

Für jeden Vorgang in einer Klasse (also ein Methoden- oder Eigenschaftenaufruf) gibt es eine Deklaration, um den Vorgang direkt aufzurufen (also die "Rohform" des Vorgangs), und eine Deklaration, um den Rohvorgang aufzurufen und einen COM-Fehler auszulösen, wenn der Vorgang nicht erfolgreich ausgeführt wird. Wenn es sich bei dem Vorgang um eine Eigenschaft handelt, wird normalerweise mit einer Compilerdirektive eine alternative Syntax für den Vorgang erstellt, die der Syntax von Visual Basic ähnelt.

Vorgänge, von denen der Wert einer Eigenschaft abgerufen wird, weisen Namen in der folgenden Form auf: GetProperty. Vorgänge, von denen der Wert einer Eigenschaft festgelegt wird, weisen Namen in der folgenden Form auf: PutProperty. Vorgänge, von denen der Wert einer Eigenschaft mit einem Zeiger auf ein ADO-Objekt festgelegt wird, weisen Namen in der folgenden Form auf: PutRefProperty.

Sie können eine Eigenschaft mit Aufrufen in der folgenden Form abrufen oder festlegen:

 
variable = objectPtr->GetProperty(); // get property value 
objectPtr->PutProperty(value); // set property value 
objectPtr->PutRefProperty(&value); // set property with object pointer 

Verwenden von Eigenschaftendirektiven

Die __declspec(property...)-Compilerdirektive ist eine Microsoft-spezifische Erweiterung der Sprache C, mit der für eine als Eigenschaft verwendete Funktion eine alternative Syntax deklariert wird. Daher können Sie Werte einer Eigenschaft ähnlich wie bei Visual Basic festlegen oder abrufen. Sie können z. B. wie folgt eine Eigenschaft festlegen und abrufen:

 
objectPtr->property = value; // set property value 
variable = objectPtr->property; // get property value 

Der Code muss nicht wie folgt aussehen:

 
objectPtr->PutProperty(value); // set property value 
variable = objectPtr->GetProperty; // get property value 

Der Compiler generiert den entsprechenden Get-, Put- oder PutRefProperty-Aufruf. Dabei basiert der Aufruf auf der deklarierten alternativen Syntax und darauf, ob die Eigenschaft gelesen oder geschrieben wird.

Die Compilerdirektive __declspec(property...) kann nur get, put oder get and put als alternative Syntax für eine Funktion deklarieren. Schreibgeschützte Vorgänge verfügen nur über eine get-Deklaration . Schreibgeschützte Vorgänge verfügen nur über eine put-Deklaration . Vorgänge, die sowohl Lese- als auch Schreibvorgänge sind, verfügen über get - und put-Deklarationen .

Mit dieser Richtlinie sind nur zwei Erklärungen möglich; Jede Eigenschaft kann jedoch drei Eigenschaftenfunktionen aufweisen: GetProperty, PutProperty und PutRefProperty. In diesem Fall verfügen nur zwei Formen der Eigenschaft über die alternative Syntax.

Beispielsweise wurde die ActiveConnection-Eigenschaft des Command-Objekts mit einer alternativen Syntax für GetActiveConnection und PutRefActiveConnection deklariert. Die PutRef-Syntax ist eine gute Wahl, weil Sie in der Praxis üblicherweise in diese Eigenschaft ein offenes Connection-Objekt aufnehmen (d. h. einen Connection-Objektzeiger). Andererseits weist das Recordset-Objekt Get-, Put- und PutRefActiveConnection-Vorgänge auf, aber keine alternative Syntax.

Auflistungen, die GetItem-Methode und die Item-Eigenschaft

ADO definiert mehrere Auflistungen, einschließlich Fields, Parameters, Properties und Errors. In Visual C++ gibt die GetItem(index) -Methode ein Element der Auflistung zurück. Index ist ein Variant-Wert, der eigentliche Wert ist ein numerischer Index des Members in der Auflistung oder eine Zeichenfolge mit dem Namen des Members.

Die __declspec(property...) -Compilerdirektive deklariert die Item -Eigenschaft als eine alternative Syntax für die grundlegende GetItem() -Methode jeder Auflistung. Für die alternative Syntax werden eckige Klammern verwendet, und sie ähnelt einem Arrayverweis. Im Allgemeinen sehen die beiden Formen wie folgt aus:

    collectionPtr->GetItem(index); 
    collectionPtr->Item[index]; 

Weisen Sie beispielsweise einem Feld eines Recordset-Objekts namens rs einen Wert zu, das aus der Authors-Tabelle der Pubs-Datenbank abgeleitet ist. Verwenden Sie die Item()-Eigenschaft, um auf das dritte Field der Fields-Auflistung des Recordset-Objekts zuzugreifen (Auflistungen werden von null indiziert; angenommen, das dritte Feld hat den Namen au_fname). Rufen Sie dann die Value()-Methode für das Field-Objekt auf, um einen Zeichenfolgenwert zuzuweisen.

Dies kann in Visual Basic auf die folgenden vier Arten ausgedrückt werden (die beiden letzten Formen gelten nur für Visual Basic, in anderen Sprachen gibt es keine Entsprechungen):

 
rs.Fields.Item(2).Value = "value" 
rs.Fields.Item("au_fname").Value = "value" 
rs(2) = "value" 
rs!au_fname = "value" 

Die Entsprechung in Visual C++ zu den ersten beiden Formen lautet:

 
rs->Fields->GetItem(long(2))->PutValue("value"); 
rs->Fields->GetItem("au_fname")->PutValue("value"); 

-oder- (die alternative Syntax für die Value -Eigenschaft wird ebenfalls dargestellt)

 
rs->Fields->Item[long(2)]->Value = "value"; 
rs->Fields->Item["au_fname"]->Value = "value"; 

COM-spezifische Datentypen

Im Allgemeinen weisen alle Visual Basic-Datentypen, die Sie in der ADO-API-Referenz finden, eine Visual C++-Entsprechung auf. Dazu gehören Standarddatentypen wie unsigned char für Byte in Visual Basic, short für Integer und long für Long. Mithilfe der Syntaxindizes können Sie genau feststellen, was für die Operanden einer bestimmten Methode oder Eigenschaft erforderlich ist.

Ausnahmen zu dieser Regel bilden die Datentypen, die nur für COM gelten: Variant, BSTR und SafeArray.

Variant

A Variant is a structured data type that contains a value member and a data type member. A Variant may contain a wide range of other data types including another Variant, BSTR, Boolean, IDispatch or IUnknown pointer, currency, date, and so on. COM also provides methods that make it easy to convert one data type to another.

Die _variant_t -Klasse kapselt und verwaltet den Variant -Datentyp.

Wenn in der ADO-API-Referenz angegeben ist, dass der Operand einer Methode oder Eigenschaft einen Wert übernimmt, bedeutet dies normalerweise, dass der Wert in einer _variant_t -Klasse übergeben wird.

This rule is explicitly true when the Parameters section in the topics of the ADO API Reference says an operand is a Variant. One exception is when the documentation explicitly says the operand takes a standard data type, such as Long or Byte, or an enumeration. Another exception is when the operand takes a String.

BSTR

BSTR (Basic STRing) ist ein strukturierter Datentyp, der eine Zeichenfolge und die Länge der Zeichenfolge enthält. COM bietet Methoden zum Zuordnen, Ändern und Freigeben eines BSTR-Werts.

Die _bstr_t -Klasse kapselt und verwaltet den BSTR -Datentyp.

Wenn in der ADO-API-Referenz angegeben ist, dass eine Methode oder Eigenschaft einen String -Wert übernimmt, bedeutet dies, dass der Wert die Form einer _bstr_t -Klasse aufweist.

Umwandlung von _variant_t- und _bstr_t-Klassen

Häufig ist es nicht erforderlich, einen _variant_t - oder _bstr_t -Wert in einem Argument für einen Vorgang zu codieren. Wenn die _variant_t - oder _bstr_t -Klasse einen Konstruktor aufweist, der mit dem Datentyp des Arguments übereinstimmt, generiert der Compiler den entsprechenden _variant_t - oder _bstr_t -Wert.

Wenn das Argument jedoch nicht eindeutig ist, wenn also der Datentyp des Arguments mit mehr als einem Konstruktor übereinstimmt, müssen Sie das Argument mit dem entsprechenden Datentyp umwandeln, um den richtigen Konstruktor aufzurufen.

Beispielsweise lautet die Deklaration für die Recordset::Open -Methode wie folgt:

 
 HRESULT Open ( 
 const _variant_t & Source, 
 const _variant_t & ActiveConnection, 
 enum CursorTypeEnum CursorType, 
 enum LockTypeEnum LockType, 
 long Options ); 

Das ActiveConnection-Argument übernimmt einen Verweis auf _variant_t, den Sie als Verbindungszeichenfolge oder als Zeiger auf eine geöffnetes Connection-Objekt codieren können.

Die richtige _variant_t wird implizit erstellt, wenn Sie eine Zeichenfolge wie "DSN=pubs; uid=sa; pwd=;" oder ein Zeiger wie "(IDispatch *) pConn".

Sie können auch explizit eine _variant_t codieren , die einen Zeiger wie "_variant_t((IDispatch *) pConn, true)" enthält. Die Umwandlung (IDispatch *) löst die Mehrdeutigkeit mit einem anderen Konstruktor auf, der einen Zeiger auf eine IUnknown-Schnittstelle annimmt.

It is a crucial, though seldom mentioned fact, that ADO is an IDispatch interface. Whenever a pointer to an ADO object must be passed as a Variant, that pointer must be cast as a pointer to an IDispatch interface.

Im letzten Fall wird das zweite boolesche Argument des Konstruktors explizit mit dem optionalen Standardwert true codiert. Durch dieses Argument ruft der Variant-Konstruktor seine AddRef()-Methode auf, dies ist der Ausgleich dafür, dass von ADO automatisch die _variant_t::Release()-Methode aufgerufen wird, wenn der ADO-Methoden- oder -Eigenschaftenaufruf abgeschlossen ist.

Safearray

SafeArray ist ein strukturierter Datentyp, der ein Array anderer Datentypen enthält. SafeArray wird als safe (sicher) bezeichnet, da dieser Datentyp Informationen zu den Grenzen der einzelnen Arraydimensionen enthält und den Zugriff auf die Arrayelemente innerhalb dieser Grenzen beschränkt.

Wenn in der ADO-API-Referenz angegeben ist, dass eine Methode oder Eigenschaft ein Array übernimmt oder zurückgibt, bedeutet dies, dass die Methode oder Eigenschaft einen SafeArray -Wert übernimmt oder zurückgibt, kein systemeigenes C/C++-Array.

Für den zweiten Parameter der OpenSchema-Methode des Connection-Objekts ist z. B. ein Array von Variant-Werten erforderlich. Diese Variant-Werte müssen als Elemente eines SafeArray-Werts übergeben werden, und dieser SafeArray-Wert muss als Wert eines anderen Variant-Werts festgelegt werden. Dieser andere Variant-Wert wird als zweites Argument von OpenSchema übergeben.

Als weiteres Beispiel ist das erste Argument der Find -Methode ein Variant -Wert, dessen Wert ein eindimensionaler SafeArray -Wert ist. Jedes optionale erste und zweite Argument von AddNew ist ein eindimensionaler SafeArray -Wert, und der Rückgabewert der GetRows -Methode ist ein Variant -Wert, dessen Wert ein zweidimensionaler SafeArray -Wert ist.

Fehlende und Standardparameter

Bei Visual Basic sind fehlende Parameter in Methoden zulässig. Die Open-Methode des Recordset-Objekts weist z. B. fünf Parameter auf, aber Sie können Zwischenparameter überspringen und nachstehende Parameter auslassen. Ein standardmäßiger BSTR- oder Variant-Wert wird je nach Datentyp des fehlenden Operanden ersetzt.

In C/C++, all operands must be specified. If you want to specify a missing parameter whose data type is a string, specify a _bstr_t containing a null string. If you want to specify a missing parameter whose data type is a Variant, specify a _variant_t with a value of DISP_E_PARAMNOTFOUND and a type of VT_ERROR. Alternatively, specify the equivalent _variant_t constant, vtMissing, which is supplied by the #import directive.

Drei Methoden bilden Ausnahmen zur üblichen Verwendung von vtMissing. Dies sind die Execute -Methoden der Objekte Connection - und Command -Objekte sowie die NextRecordset -Methode des Recordset -Objekts. Im Folgenden sind deren Signaturen aufgeführt:

 
_RecordsetPtr Invalid DDUE based on source, error:link not allowed in code, link filename:mdmthcnnexecute_HV10294345.xml( _bstr_t CommandText, VARIANT * RecordsAffected, 
 long Options ); // Connection 
_RecordsetPtr Invalid DDUE based on source, error:link not allowed in code, link filename:mdmthcmdexecute_HV10294344.xml( VARIANT * RecordsAffected, VARIANT * Parameters, 
 long Options ); // Command 
_RecordsetPtr Invalid DDUE based on source, error:link not allowed in code, link filename:mdmthnextrec_HV10294541.xml( VARIANT * RecordsAffected ); // Recordset 

Die Parameter RecordsAffected und Parameters sind Zeiger auf einen Variant-Wert. Parameter ist ein Eingabeparameter, der die Adresse eines Variant-Elements angibt, das einen einzelnen Parameter oder ein Array von Parametern enthält, der den ausgeführten Befehl ändert. RecordsAffected ist ein Ausgabeparameter, der die Adresse eines Variant-Elements angibt, bei dem die Anzahl der von der Methode betroffenen Zeilen zurückgegeben wird.

Geben Sie in der Execute-Methode des Command-Objekts an, dass keine Parameter angegeben werden, indem Sie Parameter entweder auf &vtMissing (empfohlen) oder auf den NULL-Zeiger (d. b. NULL oder null (0)) festlegen. Wird Parameters auf einen NULL-Zeiger festgelegt, ersetzt die Methode intern die Entsprechung von vtMissing und schließt dann den Vorgang ab.

Geben Sie für alle Methoden an, dass die Anzahl betroffener Datensätze nicht zurückgegeben werden soll, indem Sie RecordsAffected auf den NULL-Zeiger festlegen. In diesem Fall ist der NULL-Zeiger kein fehlender Parameter, sondern ein Kennzeichen dafür, dass die Methode die Anzahl betroffener Datensätze verwerfen soll.

Deshalb können Sie für diese drei Methoden z. B. folgenden Code schreiben:

 
pConnection->Execute("commandText", NULL, adCmdText); 
pCommand->Execute(NULL, NULL, adCmdText); 
pRecordset->NextRecordset(NULL); 

Fehlerbehandlung

In COM, most operations return an HRESULT return code that indicates whether a function completed successfully. The #import directive generates wrapper code around each "raw" method or property and checks the returned HRESULT. If the HRESULT indicates failure, the wrapper code throws a COM error by calling _com_issue_errorex() with the HRESULT return code as an argument. COM error objects can be caught in a try-catch block. (For efficiency's sake, catch a reference to a _com_error object.)

Bedenken Sie, dass es sich dabei um ADO-Fehler handelt: Sie resultieren daraus, dass der ADO-Vorgang fehlschlägt. Fehler, die vom zugrunde liegenden Anbieter zurückgegeben werden, werden als Error -Objekte in der Errors -Auflistung des Connection -Objekt angezeigt.

Die #import -Direktive erstellt nur Fehlerbehandlungsroutinen für Methoden und Eigenschaften, die in der ADO-DLL deklariert sind. Sie können jedoch den gleichen Mechanismus für die Fehlerbehandlung nutzen, indem Sie ein eigenes Makro oder eine Inlinefunktion für die Fehlerüberprüfung schreiben. Beispiele finden Sie im Thema Visual C++-Erweiterungen oder im Code in den folgenden Abschnitten.

Visual C++-Entsprechungen von Visual Basic-Konventionen

Im Folgenden finden Sie eine Zusammenfassung verschiedener Konventionen in der ADO-Dokumentation, codiert in Visual Basic, sowie deren Entsprechungen in Visual C++.

Deklarieren eines ADO-Objekts

In Visual Basic wird eine ADO-Objektvariable (in diesem Fall für ein Recordset -Objekt) wie folgt deklariert:

 
Dim rst As ADODB.Recordset 

Die Klausel "ADODB. Recordset" ist die ProgID des Recordset-Objekts , wie in der Registrierung definiert. Eine neue Instanz eines Record -Objekts wird wie folgt deklariert:

 
Dim rst As New ADODB.Recordset 

-oder-

 
Dim rst As ADODB.Recordset 
Set rst = New ADODB.Recordset 

In Visual C++ generiert die #import -Direktive intelligente Zeigerdeklarationen für alle ADO-Objekte. Beispielsweise weist eine Variable, die auf ein _Recordset -Objekt verweist, den Typ _RecordsetPtr auf und wird wie folgt deklariert:

 
_RecordsetPtr rs; 

Eine Variable, die auf eine neue Instanz eines _Recordset -Objekts verweist, wird wie folgt deklariert:

 
_RecordsetPtr rs("ADODB.Recordset"); 

-oder-

 
_RecordsetPtr rs; 
rs.CreateInstance("ADODB.Recordset"); 

-oder-

 
_RecordsetPtr rs; 
rs.CreateInstance(__uuidof(_Recordset)); 

Nachdem die CreateInstance -Methode aufgerufen wurde, kann die Variable wie folgt verwendet werden:

 
rs->Open(...); 

Beachten Sie, dass in einem Fall der Operator "." so verwendet wird, als wäre die Variable ein instance einer Klasse (rs. CreateInstance), und in einem anderen Fall wird der Operator "->" verwendet, als wäre die Variable ein Zeiger auf eine Schnittstelle (rs-Open>).

Eine Variable kann auf zwei Arten verwendet werden, da der Operator "->" überladen wird, damit sich ein instance einer Klasse wie ein Zeiger auf eine Schnittstelle verhält. Ein privates Klassenmember der instance Variable enthält einen Zeiger auf die _Recordset-Schnittstelle. Der Operator "->" gibt diesen Zeiger zurück, und der zurückgegebene Zeiger greift auf die Member des _Recordset -Objekts zu.

Codieren eines fehlenden Parameters

Zeichenfolge

Wenn Sie einen fehlenden String -Operanden in Visual Basic codieren müssen, lassen Sie lediglich den Operanden aus. Sie müssen den Operanden in Visual C++ angeben. Codieren Sie einen _bstr_t -Wert, der als Wert eine leere Zeichenfolge aufweist.

 
_bstr_t strMissing(L""); 

Variant

When you need to code a missing Variant operand in Visual Basic, you merely omit the operand. You must specify all operands in Visual C++. Code a missing Variant parameter with a _variant_t set to the special value, DISP_E_PARAMNOTFOUND, and type, VT_ERROR. Alternatively, specify vtMissing, which is an equivalent pre-defined constant supplied by the #import directive.

 
_variant_t vtMissingYours(DISP_E_PARAMNOTFOUND, VT_ERROR); 

-oder verwenden Sie-

 
...vtMissing...; 

Deklarieren einer Variante

In Visual Basic wird ein Variant -Wert wie folgt mit der Dim -Anweisung deklariert:

 
Dim VariableName As Variant 

Deklarieren Sie in Visual C++ eine Variable als _variant_t -Typ. Einige schematische _variant_t -Deklarationen sind unten angegeben.

Hinweis

[!HINWEIS] Diese Deklarationen geben Ihnen lediglich eine ungefähre Vorstellung davon, was Sie in Ihrem eigenen Programm codieren können. Weitere Informationen finden Sie in den Beispielen unten und in der Visual C++-Dokumentation.

 
_variant_t VariableName(value); 
_variant_t VariableName((data type cast) value); 
_variant_t VariableName(value, VT_DATATYPE); 
_variant_t VariableName(interface * value, bool fAddRef = true); 

Verwenden von Arrays von Varianten

In Visual Basic können Arrays von Variant -Werten mit der Dim -Anweisung codiert werden. Sie können dazu auch die Array -Funktion verwenden, wie im folgenden Beispielcode dargestellt:

 
Public Sub ArrayOfVariants 
Dim cn As ADODB.Connection 
Dim rs As ADODB.Recordset 
Dim fld As ADODB.Field 
 
cn.Open "DSN=pubs", "sa", "" 
rs = cn.OpenSchema(adSchemaColumns, _ 
 Array(Empty, Empty, "authors", Empty)) 
For Each fld in rs.Fields 
 Debug.Print "Name = "; fld.Name 
Next fld 
rs.Close 
cn.Close 
End Sub 

Im folgenden Visual C++-Beispiel wird die Verwendung von SafeArray mit _variant_t veranschaulicht.

Hinweis

[!HINWEIS] Die folgenden Hinweise entsprechen kommentierten Abschnitten im Codebeispiel.

  1. Once again, the TESTHR() inline function is defined to take advantage of the existing error-handling mechanism.

  2. Sie benötigen nur ein eindimensionales Array, sodass Sie SafeArrayCreateVector verwenden können, statt der allgemeinen SAFEARRAYBOUND -Deklaration und der SafeArrayCreate -Funktion. Der Code würde wie folgt aussehen, wenn SafeArrayCreate verwendet wird:

    
      SAFEARRAYBOUND sabound[1]; 
      sabound[0].lLbound = 0; 
      sabound[0].cElements = 4; 
      pSa = SafeArrayCreate(VT_VARIANT, 1, sabound); 
    
  3. The schema identified by the enumerated constant, adSchemaColumns, is associated with four constraint columns: TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, and COLUMN_NAME. Therefore, an array of Variant values with four elements is created. Then a constraint value that corresponds to the third column, TABLE_NAME, is specified. The Recordset that is returned consists of several columns, a subset of which is the constraint columns. The values of the constraint columns for each returned row must be the same as the corresponding constraint values.

  4. Wenn Sie mit SafeArrays vertraut sind, überrascht es Sie möglicherweise, dass SafeArrayDestroy() nicht vor dem Ende aufgerufen wird. Tatsächlich wird durch den Aufruf von SafeArrayDestroy() in diesem Fall eine Laufzeitausnahme verursacht. Der Grund dafür ist, dass der Destruktor für vtCriteria VariantClear() aufruft, wenn _variant_t außerhalb des gültigen Bereichs liegt, dadurch wird SafeArray freigegeben. Durch den Aufruf von SafeArrayDestroy, ohne dass _variant_t manuell gelöscht wird, würde der Destruktor versuchen, einen ungültigen SafeArray -Zeiger zu löschen. Wenn SafeArrayDestroy aufgerufen wird, würde der Code wie folgt aussehen:

    
      TESTHR(SafeArrayDestroy(pSa)); 
      vtCriteria.vt = VT_EMPTY; 
      vtCriteria.parray = NULL; 
    

    Es ist jedoch viel einfacher, wenn SafeArray von _variant_t verwaltet wird.

 
    #import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF", "EndOfFile") 
    #include <stdio.h> 
    
    // 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=MyUserId;pwd=MyPassword;Provider=MSDASQL;", "", "", 
    adConnectUnspecified); 
    // Note 2, Note 3 
    pSa = SafeArrayCreateVector(VT_VARIANT, 1, 4); 
    if (!pSa) _com_issue_error(E_OUTOFMEMORY); 
    
    // Specify TABLE_NAME in the third array element (index of 2). 
    
    ix[0] = 2; 
    TESTHR(SafeArrayPutElement(pSa, ix, &vtTableName)); 
    
    // There is no Variant constructor for a SafeArray, so manually set the 
    // type (SafeArray of Variant) and value (pointer to a SafeArray). 
    
    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(); 
    } 
    catch (_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(); 
    } 

Verwenden der Eigenschaft Get/Put/PutRef

In Visual Basic wird der Name einer Eigenschaft nicht dadurch qualifiziert, ob sie abgerufen oder zugewiesen wird bzw. ob ihr ein Verweis zugewiesen wurde.

    Public Sub GetPutPutRef 
    Dim rs As New ADODB.Recordset 
    Dim cn As New ADODB.Connection 
    Dim sz as Integer 
    cn.Open "Provider=sqloledb;Data Source=yourserver;" & _ 
     "Initial Catalog=pubs;Integrated Security=SSPI;" 
    rs.PageSize = 10 
    sz = rs.PageSize 
    rs.ActiveConnection = cn 
    rs.Open "authors",,adOpenStatic 
    ' ... 
    rs.Close 
    cn.Close 
    End Sub

In diesem Visual C++-Beispiel wird diePutRef-Eigenschaftget/put/ veranschaulicht.

Hinweis

[!HINWEIS] Die folgenden Hinweise entsprechen kommentierten Abschnitten im Codebeispiel.

  1. In diesem Beispiel werden zwei Formen eines fehlenden Zeichenfolgenarguments verwendet: eine explizite Konstante, strMissing, und eine Zeichenfolge, mit der der Compiler einen temporären _bstr_t -Wert erstellt, der für den Bereich der Open -Methode vorhanden ist.

  2. Es ist nicht erforderlich, den Operanden von rs-PutRefActiveConnection>(cn) in (IDispatch *) zu umwandeln, da der Typ des Operanden bereits (IDispatch *) ist.

    
     #import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF", "EndOfFile") 
     #include <stdio.h> 
    
     void main(void) 
     { 
      CoInitialize(NULL); 
      try 
      { 
      _ConnectionPtr cn("ADODB.Connection"); 
      _RecordsetPtr rs("ADODB.Recordset"); 
      _bstr_t strMissing(L""); 
      long oldPgSz = 0, 
      newPgSz = 5; 
    
     // Note 1 
      cn->Open("Provider=sqloledb;Data Source=MyServer;" 
      "Initial Catalog=pubs;Integrated Security=SSPI;", 
      strMissing, "", 
      adConnectUnspecified); 
    
      oldPgSz = rs->GetPageSize(); 
      // -or- 
      oldPgSz = rs->PageSize; 
    
      rs->PutPageSize(newPgSz); 
      // -or- 
      rs->PageSize = newPgSz; 
    
     // Note 2 
      rs->PutRefActiveConnection( cn ); 
      rs->Open("authors", vtMissing, adOpenStatic, adLockReadOnly, 
      adCmdTable); 
      printf("Original pagesize = %d, new pagesize = %d\n", oldPgSz, 
      rs->GetPageSize()); 
      rs->Close(); 
      cn->Close(); 
      } 
      catch (_com_error &e) 
      { 
      printf("Description = %s\n", (char*) e.Description()); 
      } 
      ::CoUninitialize(); 
     } 
    

Verwenden von "GetItem(x)" und "Item[x]"

Mit diesem Visual Basic-Beispiel wird die standardmäßige und die alternative Syntax für Item() dargestellt.

 
Public Sub GetItemItem 
Dim rs As New ADODB.Recordset 
Dim name as String 
rs = rs.Open "authors", "DSN=pubs;", adOpenDynamic, _ 
 adLockBatchOptimistic, adTable 
name = rs(0) 
' -or- 
name = rs.Fields.Item(0) 
rs(0) = "Test" 
rs.UpdateBatch 
' Restore name 
rs(0) = name 
rs.UpdateBatch 
rs.Close 
End Sub 

Mit diesem Visual C++-Beispiel wird Item dargestellt.

Hinweis

[!HINWEIS] Der folgende Hinweis entspricht kommentierten Abschnitten im Codebeispiel.

  1. Wenn mit Item auf die Auflistung zugegriffen wird, muss der Index 2 in long umgewandelt werden, damit ein geeigneter Konstruktor aufgerufen wird.

    
     #import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF", "EndOfFile") 
     #include <stdio.h> 
    
     void main(void) 
     { 
      CoInitialize(NULL); 
      try { 
      _RecordsetPtr rs("ADODB.Recordset"); 
      _variant_t vtFirstName; 
    
      rs->Open("authors", 
      "Provider=sqloledb;Data Source=MyServer;" 
      "Initial Catalog=pubs;Integrated Security=SSPI;", 
      adOpenStatic, adLockOptimistic, adCmdTable); 
      rs->MoveFirst(); 
    
     // Note 1. Get a field. 
      vtFirstName = rs->Fields->GetItem((long)2)->GetValue(); 
      // -or- 
      vtFirstName = rs->Fields->Item[(long)2]->Value; 
    
      printf( "First name = '%s'\n", (char*) ((_bstr_t) vtFirstName)); 
    
      rs->Fields->GetItem((long)2)->Value = L"TEST"; 
      rs->Update(vtMissing, vtMissing); 
    
      // Restore name 
      rs->Fields->GetItem((long)2)->PutValue(vtFirstName); 
      // -or- 
      rs->Fields->GetItem((long)2)->Value = vtFirstName; 
      rs->Update(vtMissing, vtMissing); 
      rs->Close(); 
      } 
      catch (_com_error &e) 
      { 
      printf("Description = '%s'\n", (char*) e.Description()); 
      } 
      ::CoUninitialize(); 
     } 
    

Umwandeln von ADO-Objektzeigern mit "(IDispatch *)"

Mit dem folgenden Visual C++-Beispiel wird die Verwendung von (IDispatch *) zum Umwandeln von ADO-Objektzeigern veranschaulicht.

Hinweis

[!HINWEIS] Die folgenden Hinweise entsprechen kommentierten Abschnitten im Codebeispiel.

  1. Specify an open Connection object in an explicitly coded Variant. Cast it with (IDispatch *) so the correct constructor will be invoked. Also, explicitly set the second _variant_t parameter to the default value of true, so the object reference count will be correct when the Recordset::Open operation ends.

  2. Der Ausdruck (_bstr_t) ist keine Umwandlung, sondern ein _variant_t-Operator, der eine _bstr_t Zeichenfolge aus dem von Value zurückgegebenen Variant extrahiert. Der Ausdruck (char*) ist keine Umwandlung, sondern ein _bstr_t-Operator , der einen Zeiger auf die gekapselte Zeichenfolge in einem _bstr_t -Objekt extrahiert. In diesem Abschnitt werden einige nützliche Verhaltensweisen von _variant_t - und _bstr_t -Operatoren veranschaulicht.

    
     #import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF", "EndOfFile") 
    
     #include <stdio.h> 
    
     void main(void) 
     { 
      CoInitialize(NULL); 
      try 
      { 
      _ConnectionPtr pConn("ADODB.Connection"); 
      _RecordsetPtr pRst("ADODB.Recordset"); 
    
      pConn->Open("Provider=sqloledb;Data Source=MyServer;" 
      "Initial Catalog=pubs;Integrated Security=SSPI;", 
      "", "", adConnectUnspecified); 
     // Note 1. 
      pRst->Open( 
      "authors", 
      _variant_t((IDispatch *) pConn, true), 
      adOpenStatic, 
      adLockReadOnly, 
      adCmdTable); 
      pRst->MoveLast(); 
     // Note 2. 
      printf("Last name is '%s %s'\n", 
      (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(); 
     }