Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Remarque
La note technique suivante n’a pas été mise à jour depuis sa première inclusion 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 la rubrique intéressante dans l’index de 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. Il existe trois façons de gérer ces données :
Liez-le à un
CString/CByteArray.Liez-le à un
CLongBinary.Ne liez pas du tout et récupérez et envoyez la valeur de données longue 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 longues ne sont pas prises en charge pour les paramètres d’une requête. Elles sont uniquement prises en charge pour outputColumns.
Liaison d’une colonne de données longues à un CString/CByteArray
Avantages:
Cette approche est simple à comprendre et vous travaillez avec des classes familières. L’infrastructure prend en CFormView charge CString l’utilisation DDX_Textde . Vous disposez de nombreuses fonctionnalités générales de chaîne ou de collection avec les CString classes CByteArray 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
Comme CString il est conçu 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 pour 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 longue dans une CString ou CByteArray, la quantité maximale de données retournée est, par défaut, 255 octets. Tout ce qui dépasse ce problème est ignoré. 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 et 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 limitation différente sur la quantité de données qu’il peut retourner dans une seule extraction. 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, passez à l’utilisation RFX_LongBinary plutôt RFX_TextRFX_Binary que pour que toutes les données puissent être récupérées.
ClassWizard lie un SQL_LONGVARCHAR à un CStringSQL_LONGVARBINARY à un SQL_LONGVARBINARY à un CByteArray pour vous. Si vous souhaitez allouer plus de 255 octets dans lesquels vous récupérez votre colonne de données longue, vous pouvez ensuite 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 exactement comme 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 longues à un 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:
Cette opération récupère une colonne de données longue entière, jusqu’à 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 longues dans un CLongBinary, les classes de base de données vérifient la taille totale de la colonne de données longue, puis allouent un HGLOBAL segment de mémoire suffisamment grand pour qu’il contienne 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 l’allocation 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 l’objet 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 le type de variable dans la boîte de dialogue Ajouter une variable membre. ClassWizard ajoute ensuite un RFX_LongBinary appel à votre DoFieldExchange appel 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. S’il est trop petit, relâchez et HGLOBAL allouez-en une la taille appropriée. Définissez ensuite m_dwDataLength pour refléter la nouvelle taille.
Dans le cas contraire, 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 d’un CLongBinary
Il n’est pas nécessaire de comprendre le fonctionnement d’une CLongBinary mise à jour, mais il peut être utile comme exemple d’envoyer des valeurs de données longues à une source de données, si vous choisissez cette troisième méthode, décrite ci-dessous.
Remarque
Pour qu’un CLongBinary champ soit inclus dans une mise à jour, vous devez appeler SetFieldDirty explicitement le champ. Si vous apportez une modification à un champ, y compris la définition de 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 valeur de 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 alerte l’infrastructure selon laquelle la valeur de l’analyseur pour cette colonne est en fait l’adresse d’un 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 volumineux binaire (blob), MFC réalloue 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 de 64 000, et les blocs suivants sont deux fois plus volumineux ; par exemple, la seconde sera 128K, la troisième est 256K, et ainsi de suite. La taille initiale est configurable.
Non lié : récupération/envoi de données directement à partir d’ODBC avec SQLGetData
Avec cette méthode, vous contournez complètement les classes de base de données et traitez la colonne de données longue vous-même.
Avantages:
Vous pouvez mettre en cache des données sur 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 longue doit figurer dans la liste de sélection du jeu d’enregistrements, mais ne doit pas être liée par l’infrastructure. 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 exige que les champs non liés apparaissent à droite des champs liés. Ajoutez donc votre colonne ou vos colonnes non liées à la fin de la liste de sélection.
Remarque
Étant donné que votre colonne de données longue n’est pas liée par l’infrastructure, les modifications apportées à celle-ci ne seront pas gérées avec CRecordset::Update des appels. Vous devez créer et envoyer vous-même les instructions SQL INSERT et UPDATE requises.