Partager via


TN043 : routines RFX

Remarque

La note technique suivante n'a pas été mise à jour depuis son inclusion initiale dans la documentation en ligne. Par conséquent, certaines procédures et rubriques peuvent être obsolètes ou incorrectes. Pour obtenir les informations les plus récentes, il est recommandé de rechercher l'objet qui vous intéresse dans l'index de la documentation en ligne.

Cette note décrit l’architecture d’échange de champs d’enregistrement (RFX). Il décrit également comment écrire une procédure RFX_ .

Vue d’ensemble de l’échange de champs d’enregistrement

Toutes les fonctions de champ recordset sont effectuées avec du code C++. Il n’y a pas de ressources spéciales ni de macros magiques. Le cœur du mécanisme est une fonction virtuelle qui doit être substituée dans chaque classe d’ensemble d’enregistrements dérivée. Elle est toujours trouvée sous cette forme :

void CMySet::DoFieldExchange(CFieldExchange* pFX)
{
    //{{AFX_FIELD_MAP(CMySet)
        <recordset exchange field type call>
        <recordset exchange function call>
    //}}AFX_FIELD_MAP
}

Le format spécial des commentaires AFX permet à ClassWizard de localiser et de modifier le code dans cette fonction. Le code qui n’est pas compatible avec ClassWizard doit être placé en dehors des commentaires de format spéciaux.

Dans l’exemple ci-dessus, <recordset_exchange_field_type_call> se présente sous la forme suivante :

pFX->SetFieldType(CFieldExchange::outputColumn);

et <recordset_exchange_function_call> se présente sous la forme suivante :

RFX_Custom(pFX, "Col2", m_Col2);

La plupart des fonctions RFX_ ont trois arguments comme indiqué ci-dessus, mais certains (par exemple RFX_Text , et RFX_Binary) ont des arguments facultatifs supplémentaires.

Plusieurs RFX_ peuvent être incluses dans chaque DoDataExchange fonction.

Consultez « afxdb.h » pour obtenir la liste de toutes les routines d’échange de champs recordset fournies avec MFC.

Les appels de champs recordset permettent d’inscrire des emplacements de mémoire (généralement des membres de données) pour stocker les données de champ pour une CMySet classe.

Notes

Les fonctions de champ Recordset sont conçues pour fonctionner uniquement avec les CRecordset classes. Ils ne sont généralement pas utilisables par d’autres classes MFC.

Les valeurs initiales des données sont définies dans le constructeur C++ standard, généralement dans un bloc avec //{{AFX_FIELD_INIT(CMylSet) et //}}AFX_FIELD_INIT des commentaires.

Chaque fonction RFX_ doit prendre en charge différentes opérations, allant du retour de l’état sale du champ à l’archivage du champ en vue de la modification du champ.

Chaque fonction qui appelle DoFieldExchange (par exemple SetFieldNull, ), IsFieldDirtyeffectue sa propre initialisation autour de l’appel à DoFieldExchange.

Fonctionnement

Vous n’avez pas besoin de comprendre ce qui suit pour utiliser l’échange de champs d’enregistrement. Toutefois, comprendre comment cela fonctionne en arrière-plan vous aidera à écrire votre propre procédure d’échange.

La DoFieldExchange fonction membre est similaire à la Serialize fonction membre : elle est chargée d’obtenir ou de définir des données vers/à partir d’un formulaire externe (dans ce cas, les colonnes du résultat d’une requête ODBC) de/vers les données membres de la classe. Le paramètre pFX est le contexte d’échange de données et est similaire au paramètre CArchive à CObject::Serialize. Le pFX (un CFieldExchange objet) a un indicateur d’opération, qui est similaire à, mais une généralisation de l’indicateur de direction CArchive . Une fonction RFX peut avoir à prendre en charge les opérations suivantes :

  • BindParam — Indique l’emplacement où ODBC doit récupérer les données de paramètre

  • BindFieldToColumn — Indiquez où ODBC doit récupérer/déposer des données outputColumn

  • Fixup — Définir CString/CByteArray des longueurs, définir le bit d’état NULL

  • MarkForAddNew— Marquer sale si la valeur a changé depuis l’appel AddNew

  • MarkForUpdate— Marquer sale si la valeur a changé depuis l’appel De modification

  • Name— Ajouter des noms de champs pour les champs marqués sale

  • NameValue— Ajoutez «< column name>= » pour les champs marqués sale

  • Value — Ajouter « » suivi d’un séparateur, par exemple « », ou « »

  • SetFieldDirty— Définir le bit d’état sale (c’est-à-dire modifié) champ

  • SetFieldNull — Définir le bit d’état indiquant la valeur Null pour le champ

  • IsFieldDirty— Valeur de retour du bit d’état sale

  • IsFieldNull — Valeur de retour du bit d’état Null

  • IsFieldNullable — Retourne TRUE si le champ peut contenir des valeurs NULL

  • StoreField — Valeur du champ Archive

  • LoadField — Recharger la valeur du champ archivé

  • GetFieldInfoValue — Retourner des informations générales sur un champ

  • GetFieldInfoOrdinal — Retourner des informations générales sur un champ

Extensions utilisateur

Il existe plusieurs façons d’étendre le mécanisme RFX par défaut. Vous pouvez

  • Ajoutez de nouveaux types de données. Par exemple :

    CBookmark
    
  • Ajouter de nouvelles procédures d’échange (RFX_).

    void AFXAPI RFX_Bigint(CFieldExchange* pFX,
        const char *szName,
        BIGINT& value);
    
  • Avoir la DoFieldExchange fonction membre de manière conditionnelle inclure des appels RFX supplémentaires ou d’autres instructions C++ valides.

    while (posExtraFields != NULL)
    {
        RFX_Text(pFX,
        m_listName.GetNext(posExtraFields),
        m_listValue.GetNext(posExtraValues));
    }
    

Remarque

Ce code ne peut pas être modifié par ClassWizard et ne doit être utilisé qu’en dehors des commentaires de format spécial.

Écriture d’un RFX personnalisé

Pour écrire votre propre fonction RFX personnalisée, il est suggéré de copier une fonction RFX existante et de la modifier à vos propres fins. La sélection du rfX approprié à copier peut rendre votre travail beaucoup plus facile. Certaines fonctions RFX ont des propriétés uniques que vous devez prendre en compte lors du choix de la copie.

RFX_Long et RFX_Int: Il s’agit des fonctions RFX les plus simples. La valeur des données n’a pas besoin d’une interprétation spéciale et la taille des données est fixe.

RFX_Single et RFX_Double: Comme RFX_Long et RFX_Int ci-dessus, ces fonctions sont simples et peuvent utiliser largement l’implémentation par défaut. Ils sont stockés dans dbflt.cpp au lieu de dbrfx.cpp, toutefois, pour permettre le chargement de la bibliothèque à virgule flottante runtime uniquement lorsqu’elles sont explicitement référencées.

RFX_Text et RFX_Binary: Ces deux fonctions prélocalisent une mémoire tampon statique pour contenir des informations de chaîne/binaire, et doivent inscrire ces mémoires tampons auprès d’ODBC SQLBindCol au lieu d’inscrire &value. En raison de cela, ces deux fonctions ont beaucoup de code de cas spécial.

RFX_Date: ODBC retourne des informations de date et d’heure dans leur propre structure de données TIMESTAMP_STRUCT. Cette fonction alloue dynamiquement un TIMESTAMP_STRUCT en tant que « proxy » pour l’envoi et la réception de données d’heure de date. Diverses opérations doivent transférer les informations de date et d’heure entre l’objet C++ CTime et le proxy TIMESTAMP_STRUCT. Cela complique considérablement cette fonction, mais il s’agit d’un bon exemple d’utilisation d’un proxy pour le transfert de données.

RFX_LongBinary: il s’agit de la seule fonction RFX de bibliothèque de classes qui n’utilise pas la liaison de colonne pour recevoir et envoyer des données. Cette fonction ignore l’opération BindFieldToColumn et, au lieu de cela, pendant l’opération Fixup, alloue le stockage pour contenir les données entrantes SQL_LONGVARCHAR ou SQL_LONGVARBINARY, puis effectue un appel SQLGetData pour récupérer la valeur dans le stockage alloué. Lorsque vous préparez à renvoyer des valeurs de données à la source de données (telles que les opérations NameValue et Value), cette fonction utilise la fonctionnalité de DATA_AT_EXEC ODBC. Pour plus d’informations sur l’utilisation de SQL_LONGVARBINARY et de SQL_LONGVARCHARs, consultez la Note technique 45 .

Lorsque vous écrivez votre propre fonction RFX_ , vous serez souvent en mesure d’implémenter CFieldExchange::Default une opération donnée. Examinez l’implémentation de Default pour l’opération en question. S’il effectue l’opération que vous écrivez dans votre fonction RFX_ , vous pouvez déléguer au CFieldExchange::Default. Vous pouvez voir des exemples d’appel CFieldExchange::Default dans dbrfx.cpp

Il est important d’appeler IsFieldType au début de votre fonction RFX et de retourner immédiatement s’il retourne FALSE. Ce mécanisme empêche les opérations de paramètre d’être effectuées sur outputColumns, et vice versa (par exemple, l’appel BindParam sur un outputColumn). En outre, IsFieldType effectue automatiquement le suivi du nombre de outputColumns (m_nFields) et des paramètres (m_nParams).

Voir aussi

Notes techniques par numéro
Notes techniques par catégorie