Partager via


Programmation ADO Visual C++

S’applique à : Access 2013, Office 2013

La documentation Référence de l'API ADO décrit les fonctionnalités de l'interface de programmation d'application (API) ADO en employant une syntaxe similaire à celle de Microsoft Visual Basic. Bien qu'elle s'adresse à tous les utilisateurs, les programmeurs ADO utilisent divers langages tels que Visual Basic, Visual C++ (avec et sans la directive #import ) et Visual J++ (avec le package de classes ADO/WFC)

Pour répondre à cette diversité, les index de la syntaxe ADO pour Visual C++ proposent une syntaxe spécifique au langage Visual C++ avec des liens vers des descriptions communes de fonctionnalités, paramètres, comportements exceptionnels, etc. de la documentation Référence de l'API ADO.

ADO est implémenté avec les interfaces COM (Component Object Model). Toutefois, pour les programmeurs, il est plus facile d'utiliser COM avec certains langages de programmation qu'avec d'autres. Par exemple, presque tous les détails liés à l'utilisation de COM sont gérés implicitement pour les programmeurs qui ont recours à Visual Basic, tandis que les programmeurs Visual C++ doivent gérer eux-mêmes ces détails.

Les sections suivantes résument les détails pour les programmeurs C et C++ à l’aide d’ADO et de la directive #import . Il se concentre sur les types de données spécifiques à COM (Variant, BSTR et SafeArray) et à la gestion des erreurs (_com_error).

Utilisation de la directive de compilateur #import

La directive #import du compilateur Visual C++ simplifie l'utilisation des méthodes et des propriétés ADO. La directive extrait le nom d'un fichier contenant une bibliothèque de types, telle que le fichier .dll ADO (Msado15.dll), et génère des fichiers d'en-tête contenant des déclarations typedef, des pointeurs intelligents pour les interfaces, ainsi que des constantes énumérées. Chaque interface est encapsulée dans une classe.

Pour chaque opération qui se produit à l'intérieur d'une classe (c'est-à-dire, un appel de méthode ou de propriété), il existe une déclaration permettant d'appeler directement l'opération (c'est-à-dire, la forme « brute » de l'opération), et une déclaration qui appelle l'opération brute et lève une exception COM si l'opération ne s'exécute pas correctement. Si l'opération est une propriété, il existe généralement une directive de compilateur qui crée une autre syntaxe si l'opération présente une syntaxe apparentée à Visual Basic.

Les opérations qui extraient la valeur d'une propriété ont un nom qui se présente sous la forme GetProperty. Les opérations qui définissent la valeur d'une propriété ont un nom du type PutProperty. Quant aux opérations qui définissent la valeur d'une propriété avec un pointeur vers un objet ADO, leur nom se présente sous la forme PutRefProperty.

Vous pouvez obtenir ou définir une propriété avec des appels se présentant comme suit :

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

Utilisation de directives de propriété

La directive de compilateur __declspec(property...) est une extension du langage C spécifique à Microsoft qui déclare une fonction utilisée comme propriété avec une syntaxe alternative. Par conséquent, vous pouvez définir ou obtenir les valeurs d'une propriété d'une façon similaire à Visual Basic. Par exemple, vous pouvez définir et obtenir une propriété comme suit :

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

Notez qu'il n'est pas utile de coder les éléments suivants :

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

Le compilateur génère l'appel Get-, Put- ou PutRefProperty approprié en fonction de la syntaxe alternative déclarée et selon que la propriété est en cours de lecture ou d'écriture.

La directive de compilateur __declspec(property...) peut uniquement déclarer une syntaxe alternative get, put ou get et put pour une fonction. Les opérations en lecture seule ne peuvent avoir qu'une déclaration get et les opérations en écriture seule une déclaration put; les opérations en lecture et en écriture ont à la fois des déclarations get et put.

Seules deux déclarations sont possibles avec cette directive ; en revanche, chaque propriété peut intégrer trois fonctions de propriété : GetProperty, PutProperty et PutRefProperty. Dans ce cas, deux formes seulement de la propriété possèdent une syntaxe alternative.

Par exemple, la propriété ActiveConnection de l'objet Command est déclarée avec une syntaxe alternative pour GetActiveConnection et PutRefActiveConnection. La syntaxe PutRef- s'avère un bon choix car, dans la pratique, il est courant de spécifier un objet Connection ouvert (c'est-à-dire, un pointeur d'objet Connection) dans cette propriété. En revanche, l'objet Recordset possède les opérations Get-, Put- et PutRefActiveConnection, mais pas de syntaxe alternative.

Collections, méthode GetItem et propriété Item

ADO définit plusieurs collections, notamment Fields, Parameters, Properties et Errors. Dans Visual C++, la méthode GetItem(index) retourne un membre de la collection. Index est une valeur de type Variant, qui représente soit un index numérique du membre de la collection, soit une chaîne contenant le nom du membre.

La directive de compilateur __declspec(property...) déclare la propriété Item en tant que syntaxe alternative de la méthode élémentaire GetItem() de chaque collection. La syntaxe alternative utilise des crochets droits et présente des similitudes avec une référence de matrice. En règle générale, les deux formes se présentent comme suit:

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

Par exemple, affectez une valeur à un champ d’un objet Recordset , nommé rs, dérivé de la table authors de la base de données pubs . Utilisez la propriété Item() pour accéder au troisième champ de la collection Fields de l’objet Recordset (les collections sont indexées à partir de zéro ; supposons que le troisième champ soit nommé au_fname). Appelez ensuite la méthode Value() sur l'objet Field pour attribuer une valeur de chaîne.

Ceci peut être exprimé en Visual Basic avec les quatre variantes suivantes (les deux dernières sont propres à Visual Basic ; les autres langages n'ont pas d'équivalents) :

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

En Visual C++, l'équivalent des deux premières variantes est :

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

-ou- (la syntaxe alternative de la propriété Value est également indiquée)

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

Types de données spécifiques à COM

En règle générale, les types de données Visual Basic que vous rencontrez dans la documentation Référence de l'API ADO possèdent un équivalent Visual C++. Il peut s'agir notamment des types de données standard unsigned char pour Byte en Visual Basic, short pour Integer et long pour Long. Consultez les index de la syntaxe pour savoir exactement quelles sont les exigences au niveau des opérandes d'une méthode ou d'une propriété donnée.

Les exceptions à cette règle sont les types de données spécifiques à COM : Variant, BSTR et 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.

La classe variant_t encapsule et gère le type de données Variant.

Lorsque la documentation Référence de l'API ADO indique qu'un opérande de méthode ou de propriété prend une valeur, cela signifie généralement que la valeur est passée dans un objet _variant_t.

Cette règle est explicitement vraie lorsque la section Paramètres dans les rubriques de la référence de l’API ADO indique qu’un opérande est un variant. Une exception est lorsque la documentation indique explicitement que l’opérande prend un type de données standard, tel que Long ou Byte, ou une énumération. Une autre exception est lorsque l’opérande prend une chaîne.

BSTR

BSTR (Basic STRing) est un type de données structuré qui contient une chaîne de caractères ainsi que la longueur de celle-ci. COM fournit des méthodes permettant d'allouer, manipuler et libérer un type BSTR.

La classe _bstr_t encapsule et gère le type de données BSTR.

Lorsque la documentation Référence de l'API ADO indique qu'une méthode ou une propriété prend une valeur de type String, cela signifie que la valeur se présente sous la forme d'un type _bstr_t.

Cast _variant_t et classes _bstr_t

Souvent, il n'est pas nécessaire de coder explicitement une classe _variant_t ou _bstr_t dans un argument d'opération. Si la classe _variant_t ou _bstr_t possède un constructeur correspondant au type de données de l'argument, le compilateur génère la classe _variant_t ou _bstr_t appropriée.

Toutefois, si l'argument est ambigu, c'est-à-dire si le type de données de l'argument correspond à plusieurs constructeurs, vous devez attribuer à l'argument le type de données approprié pour appeler le constructeur correct.

Par exemple, la déclaration pour la méthode Recordset::Open est :

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

L'argument ActiveConnection prend une référence à une classe _variant_t, que vous pouvez coder sous forme de chaîne de connexion ou de pointeur vers un objet Connection ouvert.

La _variant_t correcte sera construite implicitement si vous transmettez une chaîne telle que « DSN=pubs ; uid=sa ; pwd= ; », ou un pointeur tel que « (IDispatch *) pConn ».

Vous pouvez également coder explicitement une _variant_t contenant un pointeur tel que « _variant_t((IDispatch *) pConn, true) ». Le cast, à savoir (IDispatch *), permet d'éviter toute ambiguïté par rapport à un autre constructeur qui prend un pointeur vers une interface IUnknown.

Bien qu'il s'agisse d'un fait rarement mentionné, il est essentiel de rappeler qu'ADO est une interface IDispatch. Chaque fois qu'un pointeur d'objet ADO doit être passé en tant que Variant, ce pointeur doit être converti en pointeur vers une interface IDispatch.

Dans le dernier cas, le deuxième argument booléen du constructeur est explicitement codé avec sa valeur facultative par défaut, true. Cet argument conduit le constructeur Variant à appeler sa méthode AddRef(), ce qui neutralise l'appel automatique de la méthode _variant_t::Release() par ADO au terme de l'appel de la méthode ou de la propriété ADO.

SafeArray

SafeArray est un type de données structuré qui contient un tableau d'autres types de données. SafeArray est considéré comme étant sûr (safe en anglais) car ce type de données contient des informations sur les limites de chaque dimension du tableau, et il restreint l'accès aux éléments du tableau qui se trouvent à l'intérieur de ces limites.

Lorsque la documentation Référence de l'API ADO indique qu'une méthode ou une propriété prend ou retourne un tableau, cela signifie que la méthode ou la propriété prend ou retourne un type SafeArray, et non un tableau C/C++ natif.

For example, the second parameter of the Connection object OpenSchema method requires an array of Variant values. Those Variant values must be passed as elements of a SafeArray, and that SafeArray must be set as the value of another Variant. It is that other Variant that is passed as the second argument of OpenSchema.

Pour prendre d'autres exemples, le premier argument de la méthode Find est un Variant dont la valeur est un tableau SafeArray unidimensionnel ; chacun des deux premiers arguments facultatifs de AddNew est un tableau SafeArray unidimensionnel ; et la valeur retournée par la méthode GetRows est un type Variant dont la valeur est un tableau SafeArray à deux dimensions.

Paramètres manquants et par défaut

Visual Basic autorise les paramètres manquants dans les méthodes. Par exemple, la méthode Open de l’objet Recordset a cinq paramètres, mais vous pouvez ignorer les paramètres intermédiaires et laisser les paramètres de fin. Un BSTR ou Variant par défaut est remplacé en fonction du type de données de l’opérande manquant.

Dans le cas de C/C++, tous les opérandes doivent être spécifiés. Si vous souhaitez spécifier un paramètre manquant dont le type de données est une chaîne, spécifiez une classe _bstr_t contenant une chaîne de valeur Null. Si vous souhaitez spécifier un paramètre manquant dont le type de données est un Variant, spécifiez une classe _variant_t avec la valeur DISP_E_PARAMNOTFOUND et le type VT_ERROR. Vous pouvez également spécifier la constante _variant_t équivalente, vtMissing, fournie par la directive #import.

Il existe trois méthodes qui constituent des exceptions à l'utilisation habituelle de vtMissing. Il s'agit des méthodes Execute des objets Connection et Command, et de la méthode NextRecordset de l'objet Recordset. Voici leurs signatures :

 
_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 

Les paramètres RecordsAffected et Parameters sont des pointeurs vers un Variant. Parameters est un paramètre d'entrée qui spécifie l'adresse d'un Variant contenant un paramètre unique, ou un tableau de paramètres, qui modifiera la commande exécutée. RecordsAffected est un paramètre de sortie qui spécifie l'adresse d'un Variant lorsque le nombre de lignes affectées par la méthode est retourné.

Dans la méthode Execute de l’objet Command, indiquez qu’aucun paramètre n’est spécifié en définissant Parameters sur &vtMissing (ce qui est recommandé) ou sur le pointeur Null (c’est-à-dire NULL ou zéro (0)). Si Parameters est associé au pointeur Null, la méthode remplace en interne l'équivalent de vtMissing, puis termine l'opération.

Dans toutes les méthodes, vous pouvez indiquer que le nombre d'enregistrements affectés ne doit pas être retourné en associant RecordsAffected au pointeur Null. Dans ce cas, le pointeur Null ne représente pas réellement le paramètre manquant mais indique plutôt que la méthode doit ignorer le nombre d'enregistrements affectés.

Par conséquent, pour ces trois méthodes, le code suivant est approprié :

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

Gestion des erreurs

Dans COM, la plupart des opérations renvoient un code de retour HRESULT qui indique si une fonction a été correctement exécutée. La directive #import génère un code wrapper pour chaque méthode ou propriété « brute » et analyse le code de retour HRESULT. Si HRESULT indique un échec, le code wrapper génère une erreur COM en appelant _com_issue_errorex() avec le code de retour HRESULT en tant qu'argument. Les objets d'erreur COM peuvent être interceptés dans un bloc try-catch. (Par souci d'efficacité, interceptez une référence dans un objet _com_error.)

Rappelez-vous qu'il s'agit d'erreurs ADO : elles sont le résultat de l'échec d'une opération ADO. Les erreurs retournées par le fournisseur sous-jacent apparaissent en tant qu'objets Error dans la collection Errors de l'objet Connection.

La directive #import ne crée des routines de gestion des erreurs que pour les méthodes et les propriétés déclarées dans le fichier .dll ADO. Toutefois, vous pouvez tirer parti de ce même mécanisme de gestion des erreurs en écrivant votre propre fonction inline ou macro de détection d'erreurs. Vous trouverez des exemples dans la rubrique Extensions Visual C++ pour ADO, ou le code présenté dans les sections suivantes.

Équivalents Visual C++ des conventions Visual Basic

Vous trouverez ci-dessous un récapitulatif de plusieurs conventions décrites dans la documentation ADO, codées en Visual Basic, ainsi que leurs équivalents en Visual C++.

Déclaration d’un objet ADO

En langage Visual Basic, une variable d'objet ADO (en l'occurrence, un objet Recordset ) est déclarée comme suit :

 
Dim rst As ADODB.Recordset 

La clause « ADODB. Recordset », est le ProgID de l’objet Recordset tel que défini dans le Registre. Une nouvelle instance d'un objet Record est déclarée comme suit :

 
Dim rst As New ADODB.Recordset 

ou -

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

En langage Visual C++, la directive #import génère des déclarations de type pointeur intelligent pour tous les objets ADO. Par exemple, une variable qui pointe vers un objet _Recordset est de type _RecordsetPtr et est déclarée comme suit :

 
_RecordsetPtr rs; 

Une variable qui pointe vers une nouvelle instance d'un objet _Recordset est déclarée comme suit :

 
_RecordsetPtr rs("ADODB.Recordset"); 

ou -

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

ou -

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

Une fois que la méthode CreateInstance a été appelée, la variable peut être utilisée comme suit :

 
rs->Open(...); 

Notez que dans un cas, l’opérateur « . » est utilisé comme si la variable était une instance d’une classe (rs. CreateInstance), et dans un autre cas, l’opérateur « -> » est utilisé comme si la variable était un pointeur vers une interface (rs-Open>).

Une variable peut être utilisée de deux manières, car l’opérateur « -> » est surchargé pour permettre à un instance d’une classe de se comporter comme un pointeur vers une interface. Un membre de classe privée de la variable instance contient un pointeur vers l’interface _Recordset ; l’opérateur « -> » retourne ce pointeur ; et le pointeur retourné accède aux membres de l’objet _Recordset.

Codage d’un paramètre manquant

String

Lorsque vous devez coder un opérande String manquant en Visual Basic, il vous suffit de l'omettre. En Visual C++, vous devez spécifier l'opérande. Codez un _bstr_t qui a pour valeur une chaîne vide.

 
_bstr_t strMissing(L""); 

Variant

Lorsque vous devez coder un opérande Variant manquant en Visual Basic, il vous suffit de l'omettre. En Visual C++, vous devez spécifier tous les opérandes. Codez un paramètre Variant manquant en attribuant à un _variant_t la valeur spéciale DISP_E_PARAMNOTFOUND et le type VT_ERROR. Vous pouvez également spécifier vtMissing, qui est une constante prédéfinie équivalente fournie par la directive #import.

 
_variant_t vtMissingYours(DISP_E_PARAMNOTFOUND, VT_ERROR); 

ou utilisez -

 
...vtMissing...; 

Déclaration d’une variante

En Visual Basic, un Variant est déclaré avec l'instruction Dim comme suit :

 
Dim VariableName As Variant 

En Visual C++, déclarez une variable en lui attribuant le type _variant_t. Vous trouverez ci-dessous quelques exemples de déclarations _variant_t schématiques.

Remarque

[!REMARQUE] Ces déclarations donnent simplement une idée globale du codage que vous effectueriez dans votre propre programme. Pour plus d'informations, consultez les exemples ci-dessous, ainsi que la documentation Visual C++.

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

Utilisation de tableaux de variantes

En langage Visual Basic, les tableaux de valeurs Variant peuvent être codés à l'aide de l'instruction Dim. Vous pouvez également utiliser la fonction Array, comme illustré dans l'exemple de code suivant :

 
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 

L'exemple Visual C++ suivant illustre l'utilisation d'un tableau SafeArray avec un type _variant_t.

Remarque

[!REMARQUE] Les remarques suivantes correspondent aux sections commentées dans l'exemple de code.

  1. À nouveau, la fonction inline TESTHR() est définie pour tirer parti d'un mécanisme de gestion des erreurs existant.

  2. Vous avez seulement besoin d'un tableau unidimensionnel pour pouvoir utiliser SafeArrayCreateVector à la place de la déclaration SAFEARRAYBOUND et de la fonction SafeArrayCreate à usage général. Voici comment se présenterait le code si vous utilisiez SafeArrayCreate:

    
      SAFEARRAYBOUND sabound[1]; 
      sabound[0].lLbound = 0; 
      sabound[0].cElements = 4; 
      pSa = SafeArrayCreate(VT_VARIANT, 1, sabound); 
    
  3. Le schéma identifié par la constante énumérée , adSchemaColumns, est associé à quatre colonnes de contrainte : TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME et COLUMN_NAME. Par conséquent, un tableau de valeurs Variant avec quatre éléments est créé. Ensuite, une valeur de contrainte qui correspond à la troisième colonne, TABLE_NAME, est spécifiée. L’objet Recordset retourné se compose de plusieurs colonnes, dont un sous-ensemble est les colonnes de contrainte. Les valeurs des colonnes de contrainte pour chaque ligne retournée doivent être identiques aux valeurs de contrainte correspondantes.

  4. Ceux qui connaissent SafeArrays peuvent être surpris que SafeArrayDestroy() ne soit pas appelé avant la sortie. En fait, l’appel de SafeArrayDestroy() dans ce cas entraîne une exception d’exécution. La raison en est que le destructeur de vtCriteria appelleRa VariantClear() lorsque le _variant_t sortira de l’étendue, ce qui libérera le SafeArray. L’appel de SafeArrayDestroy, sans effacer manuellement le _variant_t, amènerait le destructeur à essayer d’effacer un pointeur SafeArray non valide. Si SafeArrayDestroy était appelé, le code se présenterait comme suit :

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

    Cependant, il est bien plus simple de laisser l'objet _variant_t gérer le tableau SafeArray.

 
    #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(); 
    } 

Utilisation de la propriété Get/Put/PutRef

En langage Visual Basic, le fait que le nom d'une propriété soit récupéré, attribué ou qu'une référence lui soit attribuée ne suffit pas à le qualifier.

    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

Cet exemple Visual C++ illustre la propriétéGet/Put/Put PutRef.

Remarque

[!REMARQUE] Les remarques suivantes correspondent aux sections commentées dans l'exemple de code.

  1. Cet exemple utilise deux formes d'un argument de chaîne manquante : une constante explicite, strMissing, et une chaîne que le compilateur utilisera pour créer un objet _bstr_t temporaire qui existera uniquement dans la cadre de la méthode Open.

  2. Il n’est pas nécessaire de caster l’opérande de rs-PutRefActiveConnection>(cn) en (IDispatch *), car le type de l’opérande est déjà (IDispatch *).

    
     #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(); 
     } 
    

Utilisation de GetItem(x) et Item[x]

Cet exemple Visual Basic illustre la syntaxe standard et alternative de Item().

 
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 

Cet exemple Visual C++ illustre Item.

Remarque

[!REMARQUE] La remarque suivante correspond aux sections commentées dans l'exemple de code.

  1. Lorsque l'accès à la collection s'effectue avec Item, l'index 2 doit être casté en long pour permettre l'appel d'un constructeur approprié.

    
     #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(); 
     } 
    

Conversion de pointeurs d'objet ADO à l'aide de (IDispatch *)

L'exemple Visual C++ suivant illustre l'utilisation de (IDispatch *) pour effectuer un cast des pointeurs d'objet ADO.

Remarque

[!REMARQUE] Les remarques suivantes correspondent aux sections commentées dans l'exemple de code.

  1. Spécifiez un objet Connection ouvert dans un Variant explicitement codé. Convertissez-le à l'aide de (IDispatch *) pour permettre l'appel du constructeur approprié. De même, attribuez explicitement au second paramètre _variant_t la valeur par défaut true de sorte que le nombre de références d'objet soit correct à l'issue de l'opération Recordset::Open.

  2. L’expression (_bstr_t) n’est pas un cast, mais un opérateur _variant_t qui extrait une chaîne _bstr_t de la variante retournée par Value. L’expression (char*) n’est pas un cast, mais un opérateur _bstr_t qui extrait un pointeur vers la chaîne encapsulée dans un objet _bstr_t . Cette section de code illustre certains comportements utiles des opérateurs _variant_t et _bstr_t.

    
     #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(); 
     }