Partager via


TN045 : prise en charge MFC/Database de longs varchar/varbinary

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 explique comment récupérer et envoyer les types de données ODBC SQL_LONGVARCHAR et SQL_LONGVARBINARY à l’aide des classes de base de données MFC.

Vue d'ensemble de la prise en charge de Long Varchar/Varbinary

Les types de données ODBC SQL_LONG_VARCHAR et SQL_LONGBINARY (appelés ici les colonnes de données longues) peuvent contenir d’énormes quantités de données. Vous pouvez gérer ces données de 3 façons :

  • Liez-les à CString/CByteArray.

  • Liez-les à CLongBinary.

  • Ne les liez pas du tout et récupérez et envoyez la valeur des données de type long manuellement, indépendamment des classes de base de données.

Chacune des trois méthodes présente des avantages et des inconvénients.

Les colonnes de données de type long ne sont pas prises en charge pour les paramètres d'une requête. Elles le sont uniquement pour outputColumns.

Liaison d'une colonne de données de type long à CString et CByteArray

Avantages :

Cette approche est simple à comprendre, et vous utilisez des classes qui vous sont familières. Le framework fournit la prise en charge de CFormView pour CString avec DDX_Text. Les classes CString et CByteArray fournissent un grand nombre de fonctionnalités de chaîne ou de collection générales, et vous pouvez contrôler la quantité de mémoire allouée localement pour contenir la valeur des données. L’infrastructure gère une ancienne copie des données de champ pendant Edit ou AddNew des appels de fonction, et l’infrastructure peut détecter automatiquement les modifications apportées aux données pour vous.

Remarque

Étant CString donné qu’elle est conçue pour travailler sur des données de caractères et CByteArray pour travailler sur des données binaires, il est recommandé de placer les données de caractères (SQL_LONGVARCHAR) CStringdans , et les données binaires (SQL_LONGVARBINARY) dans CByteArray.

Les fonctions RFX pour CString et CByteArray ont un argument supplémentaire qui vous permet de remplacer la taille par défaut de la mémoire allouée pour contenir la valeur récupérée de la colonne de données. Notez l'argument nMaxLength dans les déclarations de fonction suivantes :

void AFXAPI RFX_Text(CFieldExchange* pFX,
    const char *szName,
    CString& value,
    int nMaxLength = 255,
    int nColumnType =
    SQL_VARCHAR);

void AFXAPI RFX_Binary(CFieldExchange* pFX,
    const char *szName,
    CByteArray& value,
    int nMaxLength = 255);

Si vous récupérez une colonne de données de type long dans CString ou CByteArray, la quantité maximale de données retournées est, par défaut, 255 octets. Au-delà, rien ne sera pris en compte. Dans ce cas, l’infrastructure lève l’exception AFX_SQL_ERROR_DATA_TRUNCATED. Heureusement, vous pouvez augmenter explicitement nMaxLength à des valeurs supérieures, jusqu’à MAXINT.

Remarque

La valeur de nMaxLength est utilisée par MFC pour définir la mémoire tampon locale de la SQLBindColumn fonction. Il s'agit de la mémoire tampon locale pour le stockage des données, qui n'affecte pas réellement la quantité de données retournées par le pilote ODBC. RFX_Text et RFX_Binary effectuez un seul appel à l’aide SQLFetch de la base de données principale pour récupérer les données de la base de données principale. Chaque pilote ODBC a une propre limite sur la quantité de données qu’il peut retourner en une seule récupération. Cette limite peut être beaucoup plus petite que la valeur définie dans nMaxLength, auquel cas l’exception AFX_SQL_ERROR_DATA_TRUNCATED sera levée. Dans ces circonstances, utilisez RFX_LongBinary au lieu de RFX_Text ou RFX_Binary afin que toutes les données puissent être récupérées.

ClassWizard lie un SQL_LONGVARCHAR à un CStringSQL_LONGVARBINARY à unCByteArray. Si vous souhaitez allouer plus de 255 octets dans lesquels vous récupérez la colonne de données de type long, vous pouvez fournir une valeur explicite pour nMaxLength.

Lorsqu’une colonne de données longue est liée à un CString ou CByteArray, la mise à jour du champ fonctionne de la même façon que lorsqu’elle est liée à un SQL_VARCHAR ou SQL_VARBINARY. Pendant Edit, la valeur de données est mise en cache et ultérieurement comparée lorsqu’elle Update est appelée pour détecter les modifications apportées à la valeur de données et définir les valeurs Dirty et Null pour la colonne de manière appropriée.

Liaison d’une colonne de données de type long à CLongBinary

Si votre colonne de données longue peut contenir plus d’octets MAXINT de données, vous devez probablement envisager de la récupérer dans un CLongBinary.

Avantages :

Vous récupérez une colonne de données entière de type long, en fonction de la mémoire disponible.

Inconvénients :

Les données sont conservées en mémoire. Cette approche est également extrêmement coûteuse pour de très grandes quantités de données. Vous devez appeler SetFieldDirty le membre de données lié pour vous assurer que le champ est inclus dans une Update opération.

Si vous récupérez des colonnes de données de type long dans CLongBinary, les classes de base de données vérifient leur taille totale, puis allouent un segment de mémoire HGLOBAL assez grand pour contenir la valeur de données entière. Les classes de base de données récupèrent ensuite la valeur de données entière dans la mémoire allouée HGLOBAL.

Si la source de données ne peut pas retourner la taille attendue de la colonne de données longue, l’infrastructure lève l’exception AFX_SQL_ERROR_SQL_NO_TOTAL. Si la tentative d'allocation de la mémoire HGLOBAL échoue, une exception de mémoire standard est levée.

ClassWizard lie un SQL_LONGVARCHAR ou SQL_LONGVARBINARY à un CLongBinary pour vous. Sélectionnez CLongBinary comme type de variable dans la boîte de dialogue Ajouter une variable membre. ClassWizard ajoute ensuite un appel RFX_LongBinary à votre appel DoFieldExchange et incrémente le nombre total de champs liés.

Pour mettre à jour les valeurs de colonne de données longues, vérifiez d’abord que l’allocation HGLOBAL est suffisamment grande pour contenir vos nouvelles données en appelant ::GlobalSize sur le membre m_hData du CLongBinary. Si elle est trop petite, libérez HGLOBAL et allouez une mémoire de la taille appropriée. Définissez ensuite m_dwDataLength pour refléter la nouvelle taille.

Sinon, si m_dwDataLength est supérieure à la taille des données que vous remplacez, vous pouvez libérer et réallouer le HGLOBALou le laisser alloué. Veillez à indiquer le nombre d’octets réellement utilisés dans m_dwDataLength.

Fonctionnement de la mise à jour de CLongBinary

Il n'est pas nécessaire de comprendre le fonctionnement de la mise à jour de CLongBinary, mais cela peut être utile pour savoir comment envoyer des valeurs de données de type long à une source de données, si vous choisissez cette troisième méthode, décrite ci-dessous.

Remarque

Pour qu'un champ CLongBinary soit inclus dans une mise à jour, vous devez appeler explicitement SetFieldDirty pour ce champ. Si vous apportez des modifications à un champ, notamment en lui affectant la valeur Null, vous devez appeler SetFieldDirty. Vous devez également appeler SetFieldNull, avec le deuxième paramètre ayant la valeur FALSE, pour marquer le champ comme ayant une valeur.

Lors de la mise à jour d’un CLongBinary champ, les classes de base de données utilisent le mécanisme de DATA_AT_EXEC ODBC (consultez la documentation ODBC sur SQLSetPosl’argument rgbValue). Lorsque l’infrastructure prépare l’instruction insert ou update, au lieu de pointer vers les HGLOBAL données contenant les données, l’adresse du CLongBinary framework est définie comme valeurde la colonne à la place et l’indicateur de longueur défini sur SQL_DATA_AT_EXEC. Plus tard, lorsque l’instruction de mise à jour est envoyée à la source de données, SQLExecDirect retourne SQL_NEED_DATA. Cela indique à le framework que la valeur du paramètre pour cette colonne est en réalité l'adresse de CLongBinary. L’infrastructure appelle SQLGetData une fois avec une petite mémoire tampon, s’attendant à ce que le pilote retourne la longueur réelle des données. Si le pilote retourne la longueur réelle de l'objet BLOB, MFC réaffecte autant d'espace que nécessaire pour extraire l'objet BLOB. Si la source de données retourne SQL_NO_TOTAL, indiquant qu’elle ne peut pas déterminer la taille de l’objet BLOB, MFC crée des blocs plus petits. La taille initiale par défaut est 64 Ko, et les blocs suivants auront une taille deux fois plus grande ; par exemple, le deuxième aura une taille de 128 Ko, le troisième une taille de 256 Ko, et ainsi de suite. La taille initiale est configurable.

Absence de liaison : récupération et envoi des données directement depuis ODBC avec SQLGetData

Avec cette méthode, vous ignorez complètement les classes de base de données et gérez vous-même la colonne de données de type long.

Avantages :

Vous pouvez mettre en cache les données sur le disque si nécessaire, ou décider dynamiquement de la quantité de données à récupérer.

Inconvénients :

Vous n’obtenez pas le framework ni AddNew la prise en charge, et vous devez écrire du code vous-même pour effectuer des fonctionnalités de base (Deletefonctionne toutefois, car il ne s’agit Edit pas d’une opération au niveau de la colonne).

Dans ce cas, la colonne de données de type long doit figurer dans la liste de sélection de l'ensemble d'enregistrements, mais le framework ne doit pas la lier. Pour ce faire, vous devez fournir votre propre instruction SQL via GetDefaultSQL ou en tant qu’argument lpszSQL à CRecordsetla Open fonction, et ne pas lier la colonne supplémentaire à un appel de fonction RFX_. ODBC requiert que les champs indépendants s'affichent à droite des champs liés. En conséquence, ajoutez la ou les colonnes indépendantes à la fin de la liste de sélection.

Remarque

Étant donné que la colonne de données de type long n'est pas liée par le framework, les modifications qui y sont apportées ne sont pas gérées avec des appels CRecordset::Update. Vous devez créer et envoyer vous-même les instructions SQL INSERT et UPDATE requises.

Voir aussi

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