VI. L'objet Recordset▲
Avant de nous lancer dans des exemples concrets, nous allons voir quelques propriétés, méthodes et événements intéressants de l'objet Recordset. Je vais faire assez bref, et nous verrons les concepts intéressants plus en détail dans la troisième partie de cet article.
VI-A. Propriétés▲
Je ne vais pas reprendre celles qui définissent le curseur.
VI-A-1. AbsolutePosition▲
Renvoie ou définit la position de l'enregistrement courant dans le Recordset. Toujours disponible avec les curseurs non en avant seulement.
VI-A-2. Bookmark▲
Permet d'utiliser des signets pour marquer les enregistrements. Toujours disponible avec les curseurs non en avant seulement.
VI-A-3. CacheSize▲
Renvoie ou définit le nombre d'enregistrements qui vont être stockée dans le cache.
VI-A-4. EditMode▲
Indique le statut de modification de l'enregistrement en cours.
Peut prendre les valeurs adEditNone, adEditInProgress, adEditAdd, adEditDelete
Très utile pour savoir si des actions sont en cours sur le recordset, ce qui permet le cas échéant d'annuler ou de valider ces modifications.
VI-A-5. Filter▲
Permet de filtrer les enregistrements d'un recordset selon les critères spécifiés. Le Recordset filtré se comporte comme un nouvel objet recordset. En général cette propriété ne s'utilise pas sur les recordset côté serveur, car elle tend à faire s'effondrer les performances. Par contre on l'utilise beaucoup lors des traitements par lot des curseurs clients. Le filtre peut être de deux sortes :
Filtre SQL : il s'utilise comme une clause WHERE sans le WHERE.
Une des valeurs prédéfinies
Constante |
Valeur |
Description |
---|---|---|
AdFilterAffectedRecords |
2 |
Filtre les enregistrements affectés par le dernier appel d'une méthode Delete, Resync, UpdateBatch ou CancelBatch. |
AdFilterConflictingRecords |
5 |
Filtre les enregistrements n'ayant pas pu être modifiés lors de la dernière mise à jour |
AdFilterFetchedRecords |
3 |
Filtre les enregistrements présents dans le cache |
adFilterNone |
0 |
Enlève le Filtre ce qui rétabli le recordset d'origine |
AdFilterPendingRecords |
1 |
Filtre les enregistrements en attente de mise à jour. Applicable uniquement pour les traitements par lot. |
VI-A-6. Index▲
Définit l'index en cours dans le recordset. Uniquement utilisé avec la méthode Seek.
VI-A-7. MarshalOptions▲
Définit le mode de mise à jour lors de la reconnexion d'un recordset déconnecté. Peut prendre les valeurs
AdMarshalAll, adMarshalModifiedOnly.
Clients
VI-A-8. MaxRecords▲
Permet de définir un nombre maximum d'enregistrements que la requête peut renvoyer.
VI-A-9. RecordCount▲
Renvoie le nombre d'enregistrements disponible dans le recordset. Toujours disponible avec les curseurs qui ne sont pas de type « en avant seulement ».
VI-A-10. Sort▲
S'utilise avec une chaîne contenant le(s) nom(s) de(s) champ(s) suivi de ASC ou DESC, chaque champ étant séparé par une virgule. Préférez toujours un tri par le SQL qui est beaucoup plus performant sur les recordset côté serveur.
VI-A-11. Source▲
Renvoie la source des données d'un recordset. Lorsqu'il s'agit d'un objet Command, renvoie la propriété CommandText de celui-ci.
VI-A-12. State▲
Renvoie toujours l'état du recordset (fermé / ouvert). Dans le cas d'une connection asynchrone peut prendre les valeurs adStateConnecting, adStateExecuting, adStateFetching. Presque uniquement utilisé dans les cas asynchrones
VI-A-13. Status▲
Cette propriété est très importante, nous la reverrons d'ailleurs plus loin dans cet article. Elle indique l'état de l'enregistrement en cours lors d'une opération globale (ex. : mise à jour par lot). Peut prendre une ou plusieurs des valeurs suivantes :
Constante |
Valeur |
Description |
---|---|---|
adRecOK |
0 |
Mise à jour de l'enregistrement réussie |
adRecNew |
1 |
L'enregistrement est nouveau |
adRecModified |
2 |
L'enregistrement a été modifié |
adRecDeleted |
4 |
L'enregistrement a été supprimé |
adRecUnmodified |
8 |
L'enregistrement n'a pas été modifié |
adRecInvalid |
16 |
L'enregistrement n'a pas été sauvegardé parce que son signet n'est pas valide |
adRecMultipleChanges |
64 |
L'enregistrement n'a pas été sauvegardé parce que cela aurait affecté plusieurs enregistrements |
adRecPendingChanges |
128 |
L'enregistrement n'a pas été sauvegardé parce qu'il renvoie à une insertion en attente |
adRecCanceled |
256 |
L'enregistrement n'a pas été sauvegardé parce que l'opération a été annulée |
adRecCantRelease |
1024 |
Le nouvel enregistrement n'a pas été sauvegardé à cause du verrouillage d'enregistrements existants |
adRecConcurrencyViolation |
2048 |
L'enregistrement n'a pas été sauvegardé à cause d'un accès concurrentiel optimiste |
adRecIntegrityViolation |
4096 |
L'enregistrement n'a pas été sauvegardé parce que l'utilisateur n'a pas respecté les contraintes d'intégrité |
adRecMaxChangesExceeded |
8192 |
L'enregistrement n'a pas été sauvegardé parce qu'il y avait trop de modifications en attente |
Dans le cas d'un traitement par lot il est indispensable d'aller lire cette propriété pour les enregistrements n'ayant pu être mis à jour.
VI-B. Propriétés dynamiques▲
On utilise ces propriétés en passant par la collection Properties de l'objet recordset. Elles dépendent principalement du fournisseur. Il en existe beaucoup ; je vous en cite quelques-unes que nous utiliserons dans des exemples. Les propriétés dynamiques se valorisent en générales après la définition du fournisseur pour l'objet, dans certains cas, après l'ouverture de l'objet.
VI-B-1. IrowsetIdentity▲
Permet d'implémenter l'interface Rowset OLEDB sur les curseurs serveurs. Certains contrôles ont besoin de cette interface pour afficher les données. Attends une valeur booléenne.
Exemple d'utilisation
Serveurs
VI-B-2. Optimize▲
Permet de créer un index sur un champ (objet Field) d'un recordset côté client. Cet index n'existe que dans le jeu d'enregistrements, mais n'est pas créé dans la base de données sous-jacente. L'ajout d'un index peut permettre un accroissement important des performances sur l'utilisation des recherches ou des filtres. Dans l'exemple suivant, j'ajoute un index au champ « Author » avant d'exécuter le filtre :
Set
Cnn1 =
New
ADODB.Connection
Cnn1.Open
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\biblio.mdb ;User Id=Admin; Password="
Set
MonRs =
New
ADODB.Recordset
With
MonRs
.CursorLocation
=
adUseClient
.ActiveConnection
=
Cnn1
.Open
"SELECT * FROM Authors"
, , adOpenStatic
, adLockOptimistic
, adCmdText
.Fields
(
"Author"
).Properties
(
"Optimize"
) =
True
.Filter
=
"[ Author] like '*a'"
End
With
Clients
VI-B-3. Resync Command▲
Permet de synchroniser un recordset créé à partir d'une jointure, lors de la modification ou de l'ajout de la clef étrangère d'une des tables. S'utilise toujours en conjonction avec la propriété dynamique « Unique Table ». Attends une chaîne SQL étant la commande de synchronisation.
Évidemment; on peut se passer de cette propriété en réexécutant les requêtes plutôt que de les synchroniser. Il ne faut toutefois pas perdre de vue que le coût d'exécution n'est pas le même.
Comme vous devez spécifier la table qui subira les modifications, vous devez aussi préciser la clef primaire de celle-ci à l'aide du marqueur (?).
Reprenons l'exemple ébauché dans la discussion sur les curseurs, nous allons donc utiliser une requête similaire à :
SELECT
*
FROM
Publishers, Titles WHERE
Publishers.PubID =
Titles.PubID
Sous la forme simplifiée à des fins de lisibilité :
SELECT
Publishers.PubID, Publishers.Name
, Titles.Title, Titles.ISBN, Titles.PubID
FROM
Publishers , Titles
WHERE
Publishers.PubID =
Titles.PubID
Le but étant toujours de corriger le titre en changeant l'éditeur.
Nous allons utiliser le code suivant :
Dim
Cnn1 As
ADODB.Connection
, MonRs As
ADODB.Recordset
Set
Cnn1 =
New
ADODB.Connection
Cnn1.Open
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\biblio.mdb ;User Id=Admin; Password="
Set
MonRs =
New
ADODB.Recordset
With
MonRs
.CursorLocation
=
adUseClient
.ActiveConnection
=
Cnn1
.Open
"SELECT Publishers.PubID, Publishers.Name, Titles.Title, Titles.ISBN, Titles.PubID FROM Publishers, Titles WHERE Publishers.PubID = Titles.PubID"
, _
, adOpenStatic
, adLockOptimistic
, adCmdText
.Properties
(
"Unique Table"
) =
"Titles"
'car les modifications réelles des données ne porteront que sur cette table
.Properties
(
"Resync Command"
) =
"SELECT Publishers.PubID, Publishers.Name, Titles.Title, Titles.ISBN, Titles.PubID FROM Publishers, _
Titles WHERE Publishers.PubID
=
Titles.PubID
AND
Titles.ISBN
=
?"
' où Titles.ISBN=? précise la clef primaire de la table déclarée dans unique table
.Find
"Title='Evaluating Practice'"
.Fields
(
"Titles.PubId"
) =
192
'Numéro de l'éditeur Alpha Books
.Fields
(
"Title"
) =
.Fields
(
"Title"
) &
"s"
.Update
.Resync
adAffectCurrent
Debug.Print
.Fields
(
"Name"
).Value
End
With
Nous voyons alors que la valeur apparaissant dans la fenêtre exécution est la bonne et que la modification désirée a bien eu lieu dans la table.
Clients
VI-B-4. Unique Table, Unique Catalog et Unique Schema▲
Permet de désigner une table qui sera la cible unique des modifications d'un recordset issu d'une requête avec jointure. La clef primaire de cette table devient alors la clef primaire de tout le recordset.
Clients.
VI-B-5. Update Criteria▲
Définit comment le moteur de curseur va construire l'identification de l'enregistrement cible d'une modification, c'est-à-dire les valeurs qui apparaîtront dans le WHERE de la requête UPDATE. Prend une des valeurs suivantes :
Constante |
Valeur |
Description |
---|---|---|
AdCriteriaKey |
0 |
Utilise uniquement les valeurs des champs clefs. |
AdCriteriaAllCols |
1 |
Utilise les valeurs de tous les champs. (identique à un verrou optimiste) |
AdCriteriaUpdCols |
2 |
Utilise les valeurs des champs modifiés et des champs clefs (défaut) |
AdCriteriaTimeStamp |
3 |
Utilise le champ TimeStamp au lieu des champs clef. |
Attention à l'utilisation de adCriteriaKey. Ceci implique que l'enregistrement sera identifié correctement, et que la valeur sera mise à jour même si elle a été modifiée par quelqu'un d'autre. N'oubliez pas que les valeurs utilisées par le moteur de curseur sont les valeurs stockées dans la propriété OriginalValue des objets Fields concernés.
Clients
VI-B-6. Update Resync▲
Définit comment le recordset est synchronisé après un appel de la méthode Update ou UpdateBatch. N'oubliez pas que seuls les enregistrements modifiés ou ajoutés sont concernés par cette synchronisation. Prend une ou plusieurs des valeurs suivantes :
Constante |
Valeur |
Description |
---|---|---|
AdResyncNone |
0 |
Pas de synchronisation |
AdResyncAutoIncrement |
1 |
Tente de renvoyer les valeurs générées automatiquement par le SGBD |
AdResyncConflicts |
2 |
Synchronise tous les enregistrements n'ayant pas pu être mis à jour lors du dernier appel de la méthode Update. |
AdResyncUpdates |
4 |
Synchronise tous les enregistrements mis à jour |
AdResyncInserts |
8 |
Synchronise tous les enregistrements ajoutés |
AdResyncAll |
15 |
Agit comme toutes les synchronisations précédentes. |
Attention, le fait de paramétrer la propriété avec adResyncInserts ne suffira pas pour récupérer la valeur des champs à numérotation automatique. Dans ce cas vous devrez utiliser :
MonRs.Properties
(
"Update Resync"
) =
adResyncAutoIncrement +
adResyncInserts
Clients
VI-C. Collection Fields▲
Chaque enregistrement d'un recordset est composé d'une collection Fields représentant les champs de l'enregistrement. Chaque objet Field possède un certain nombre de propriétés (type, taille, précision, etc.) qui sont propres au champ. Ils possèdent aussi tous une collection de propriétés dynamiques. Enfin ils possèdent aussi trois propriétés de « valeurs ».
OriginalValue est la valeur du champ lors de la création du recordset. À chaque mise à jour réussie de l'enregistrement, cette propriété se synchronise avec la base. Nous verrons les problèmes que cela peut poser lors des traitements par lot.
UnderlyingValue est la valeur enregistrée dans la base du point de vue de l'utilisateur. C'est la propriété la plus difficile à appréhender. Si le curseur reflète les modifications de la base, cette propriété suit les modifications, sinon elle doit être synchronisée pour être juste.
Value est la valeur en cours du champ dans le recordset (pas nécessairement dans la base).
Nous verrons dans les exemples les utilisations de ces propriétés
VI-D. Méthodes▲
VI-D-1. AddNew▲
Ajoutes un nouvel enregistrement au recordset. De la forme
recordset .AddNew FieldList, Values
Ou FieldList et Values sont des paramètres facultatifs permettant d'entrer directement des valeurs dans le nouvel enregistrement.
Dès l'appel de AddNew, l'enregistrement créé devient l'enregistrement en cours.
Attention, l'utilisation des paramètres lance un Update implicite. Par exemple:
With
MonRs
.AddNew
.Fields
(
"Author"
) =
"RABILLOUD, Jean-Marc"
.Fields
(
"year born"
) =
1967
.Update
End
With
Est équivalent à :
MonRs.AddNew
Array
(
"Author"
, "year born"
), Array
(
"RABILLOUD, Jean-Marc"
, 1967
)
VI-D-2. CancelBatch▲
Annule les modifications en attente dans un traitement par lot. De la forme :
recordset.CancelBatch AffectRecords
Où AffectRecords détermine si la méthode porte sur un ou plusieurs enregistrements. Il peut prendre les valeurs adAffectAll, adAffectGroup ou adAffectCurrent.
Déclenche en fait un appel de la méthode CancelUpdate sur tous les enregistrements modifiés, ajoutés ou supprimés du recordset. Attention, comme toutes les opérations par lot, la méthode peut définir des erreurs dans la collection Errors de l'objet connection, sans interrompre le traitement.
VI-D-3. CancelUpdate▲
Annule les modifications apportées sur l'enregistrement en cours, ou annule l'enregistrement créé par AddNew.
VI-D-4. Clone▲
Duplique un objet Recordset. Les clones sont synchronisés avec l'original jusqu'à l'application de la méthode Requery sur celui-ci.
VI-D-5. Delete▲
Supprime un ou plusieurs enregistrements. De la forme :
recordset.Delete AffectRecords
Où AffectRecords détermine si la méthode porte sur l'enregistrement en cours ou sur tous les enregistrements qui correspondent à la propriété Filter.
VI-D-6. Find▲
Recherche les enregistrements répondant aux critères spécifiés. Cette méthode ne permet une recherche que sur un seul champ. De la forme :
recordset.Find (criteria, SkipRows, searchDirection, start)
Où SkipRows est une valeur facultative qui donne le décalage par rapport à la ligne en cours ou au paramètre Start, quand il est défini.
SearchDirection est une valeur facultative qui peut prendre les valeurs adSearchForward ou adSearchBackward
Start donne la position de l'enregistrement de démarrage de la recherche.
Criteria est l'expression du critère de recherche. Il se compose toujours du nom du champ suivi de l'opérateur de comparaison suivi de la valeur.
Le nom du champ doit être entre crochets s'il contient un espace
L'opérateur doit être (« > » (supérieur à), « < » (inférieur à), « = » (égal) « >= » (supérieur à ou égal), « <= » (inférieur à ou égal), « <> » (différent de) ou « Like » (concordance avec un modèle).)
La valeur doit être entourée de simples quotes ' s'il s'agit d'un texte, de dièse # si c'est une date ou de rien pour une valeur numérique.
Si aucun enregistrement correspondant n'est trouvé, le recordset se positionnera sur EOF ou BOF, selon le sens de la recherche.
N.B : Cette méthode est très coûteuse en ressource, essayez toujours de privilégier une méthode SQL sur les curseurs serveur.
VI-D-7. GetRows▲
Cette méthode permet de convertir un Recordset en tableau à deux dimensions (champ, enregistrement) de la forme :
Tableau = recordset.GetRows( Rows, Start, Fields )
Où Rows représente le nombre d'enregistrements à convertir, si la valeur est -1 tous les enregistrements seront convertis à partir de la position donnée par le paramètre « Start », s'il est omis tous les enregistrements du Recordset seront convertis.
Start donne la position du premier enregistrement à convertir. Peut prendre les valeurs adBookmarkCurrent, adBookmarkFirst, adBookmarkLast
Fields est la liste des champs devant être converti.
Après l'appel de la méthode, le recordset se positionne sur le premier enregistrement non converti ou sur EOF.
VI-D-8. GetString▲
Renvoie le recordset sous forme d'une chaîne. De la forme :
Set Variant = recordset.GetString(StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)
Où StringFormat est toujours AdClipString
Les lignes sont délimitées par RowDelimiter, les colonnes par ColumnDelimiter et les valeurs NULL par NullExpr. Ces trois paramètres sont valides uniquement avec adClipString.
VI-D-9. MoveFirst, MoveLast, MoveNext, MovePrevious▲
Ces méthodes permettent de se déplacer dans le jeu d'enregistrements. À la différence des mêmes méthodes DAO, le déplacement de l'enregistrement en cours valide l'ensemble des modifications effectuées.
VI-D-10. Open▲
Ouvre le Recordset. Nous verrons plus loin qu'il y a plusieurs méthodes pour obtenir un jeu d'enregistrements. De la forme :
recordset.Open Source, ActiveConnection, CursorType, LockType, Options
CursorType et LockType sont les propriétés du même nom, ActiveConnection est un objet Connection (explicite) ou une chaîne de connexion (Implicite).
Options peut prendre une ou plusieurs valeurs (masque binaire) de CommandTypeEnum et de ExecuteOptionEnum qui sont des paramètres de la méthode Execute de l'objet Command.
CommandTypeEnum |
---|
Constantes |
Valeur |
Description |
---|---|---|
AdCmdUnspecified |
-1 |
Pas de spécification de type |
AdCmdText |
1 |
CommandText correspond à la définition textuelle d'une commande ou d'un appel de procédure stockée. |
AdCmdTable |
2 |
CommandText correspond au nom de table dont les colonnes sont toutes renvoyées par une requête SQL générée en interne. |
AdCmdStoredProc |
4 |
CommandText correspond au nom d'une procédure stockée. |
AdCmdUnknown |
8 |
Valeur utilisée par défaut. Le type de commande de la propriété CommandText est inconnu. |
AdCmdFile |
256 |
CommandText correspond au nom de fichier d'un Recordset permanent. |
adCmdTableDirect |
512 |
CommandText correspond à un nom de table dont les colonnes sont toutes renvoyées. |
Ce paramètre doit être passé si le texte de la commande n'est pas une commande SQL, sous peine de ralentir le traitement.
ExecuteOptionEnum |
---|
Constantes |
Valeur |
Description |
---|---|---|
adAsyncExecute |
16 |
Indique que la commande doit s'exécuter en mode asynchrone |
adAsyncFetch |
32 |
Indique que les lignes restant après la quantité initiale spécifiée dans la propriété « Initial Fetch Size » doivent être récupérées en mode asynchrone. Si une ligne nécessaire n'a pas été récupérée, le chemin principal est bloqué jusqu'à ce que la ligne demandée devienne disponible. |
adAsyncFetchNonBlocking |
64 |
Indique que le chemin principal n'est jamais bloqué pendant la recherche. Si la ligne demandée n'a pas été recherchée, la ligne en cours se place automatiquement en fin de fichier. Cela n'a pas d'effet si le recordset est ouvert en mode adCmdTableDirect |
Ce paramètre doit être passé si l'on travaille en mode Asynchrone.
VI-D-11. Requery▲
Recrée le jeu d'enregistrements en réexécutant la requête. De la forme :
recordset.Requery Options
Où options est le même paramètre que dans le cas de la méthode Open.
Comme la requête est exécutée à nouveau, il peut y avoir des enregistrements en plus ou en moins ou provoquant des conflits du fait des actions d'autres utilisateurs. L'appel de la méthode déclenche une erreur si l'enregistrement en cours est en mode édition.
Attention, il n'est pas possible de modifier les paramètres du curseur dans l'appel de Requery. Pour modifier le curseur, vous devez utiliser Close puis Open.
VI-D-12. Resync▲
Met à jour le jeu d'enregistrements. Utilisée seulement sur des curseurs statiques ou en avant seulement ; si le curseur est côté client, il ne doit pas être en lecture seule. De la forme
recordset.Resync AffectRecords, ResyncValues
Où AffectRecords spécifie les enregistrements à mettre à jour et ResyncValues précise si les modifications sont écrasées. Si la valeur est adResyncAllValues, toutes les modifications sont écrasées, on repart avec un recordset d'origine, si la valeur est adResyncUnderlyingValues les modifications en cours sont préservées.
Voyons comment cela fonctionne▲
Un objet Recordset peut être vu comme une collection d'enregistrements, chacun étant composé d'objets Field (champ). Lors de la création du recordset, chaque champ possède trois propriétés, OriginalValue, Value et UnderlyingValue qui représente la valeur du champ. Lorsque l'on fait des modifications on modifie la propriété Value, mais pas UnderlyingValue. Par comparaison des deux, le Recordset peut toujours « marquer » les enregistrements modifiés. Si on procède à une synchronisation des valeurs de la base, les propriétés UnderlyingValue reflètent les vraies valeurs de la base, mais les propriétés Valeurs peuvent ne pas être modifiées. Le fait de synchroniser le recordset peut donc permettre de voir par avance si des valeurs ont été modifiées par un autre utilisateur, en comparant les propriétés UnderlyingValue et OriginalValue avant de déclencher une mise à jour.
VI-D-13. Save▲
Sauvegarde le Recordset comme un fichier. Un tel Recordset est appelé jeu d'enregistrements permanent. De la forme recordset.Save FileName, PersistFormat
Où PersistFormat, précise si le recordset est sauvegardé comme un fichier XML ou selon un format spécifique. Nous verrons dans les exemples comment on peut utiliser ces recordset persistant, mais sachez dès à présent qu'il n'est pas nécessaire d'avoir le fournisseur qui a créé le recordset pour pouvoir l'ouvrir.
VI-D-14. Seek▲
Permet de faire une recherche multichamp sur les recordset indexés. Ne s'utilise que sur les curseurs serveurs. De la forme :
recordset.Seek KeyValues, SeekOption
Où KeyValues est une suite de valeurs de type « Variant ». Un index consiste en une ou plusieurs colonnes ou le tableau contient autant de valeurs qu'il y a de colonne, permettant ainsi la comparaison avec chaque colonne correspondante.
SeekOption peut prendre les valeurs suivantes :
Constante |
Valeur |
Description |
---|---|---|
adSeekFirstEQ |
1 |
Recherche la première clef égale à KeyValues |
adSeekLastEQ |
2 |
Recherche la dernière clef égale à KeyValues. |
adSeekAfterEQ |
4 |
Recherche soit une clef égale à KeyValues ou juste après l'emplacement où la correspondance serait intervenue. |
adSeekAfter |
8 |
Recherche une clef juste après l'emplacement où une correspondance avec KeyValues est intervenue. |
adSeekBeforeEQ |
16 |
Recherche soit une clef égale à KeyValues où juste avant l'emplacement où la correspondance serait intervenue. |
adSeekBefore |
32 |
Recherche une clef juste avant l'emplacement où une correspondance avec KeyValues est intervenue. |
Pour utiliser la méthode Seek, il faut que le recordset supporte les index et que la commande soit ouverte en adCmdTableDirect.
Comme vous le verrez dans l'exemple le principe est simple, on ajoute un ou des index sur le(s) champ(s) cible de la recherche, et on passe le tableau des valeurs cherchées à la méthode Seek.
Serveurs
VI-D-15. Supports▲
Cette méthode est la meilleure amie du développeur ADO. Elle permet de savoir si un recordset donné va accepter une fonctionnalité spécifique. De la forme :
boolean = recordset.Supports( CursorOptions )
Où CursorOptions peut prendre les valeurs suivantes :
Constante |
Valeur |
Description |
---|---|---|
adAddNew |
16778240 |
Vous pouvez utiliser la méthode AddNew pour ajouter de nouveaux enregistrements. |
adApproxPosition |
16384 |
Vous pouvez lire et définir les propriétés AbsolutePosition et AbsolutePage. |
adBookmark |
8192 |
Vous pouvez utiliser la propriété Bookmark pour accéder à des enregistrements spécifiques. |
adDelete |
16779264 |
Vous pouvez utiliser la méthode Delete pour supprimer des enregistrements. |
adFind |
524288 |
Vous pouvez utiliser la méthode Find pour localiser une ligne dans un Recordset. |
adHoldRecords |
256 |
Vous pouvez extraire plus d'enregistrements ou modifier la position d'extraction suivante sans valider toutes les modifications en attente. |
adIndex |
8388608 |
Vous pouvez utiliser la propriété Index pour donner un nom à un index. |
adMovePrevious |
512 |
Vous pouvez utiliser les méthodes MoveFirst et MovePrevious, et les méthodes Move ou GetRows pour faire reculer la position de l'enregistrement en cours sans recourir à des signets. |
adNotify |
262144 |
Indique que le fournisseur gère les événements du recordset |
adResync |
131072 |
Vous pouvez mettre à jour le curseur avec les données visibles dans la base de données sous-jacente, au moyen de la méthode Resync. |
adSeek |
4194304 |
Vous pouvez utiliser la méthode Seek pour localiser une ligne dans un Recordset. |
adUpdate |
16809984 |
Vous pouvez utiliser la méthode Update pour modifier les données existantes |
adUpdateBatch |
65536 |
Vous pouvez utiliser la mise à jour par lots (méthodes UpdateBatch et CancelBatch) pour transmettre des groupes de modifications au fournisseur. |
On utilise dans le code la méthode Supports pour savoir comment va réagir le recordset et éviter de faire de la gestion d'erreurs a posteriori.
VI-D-16. Update▲
Sauvegarde les modifications apportées à l'enregistrement en cours. De la forme :
recordset.Update Fields, Values
Où Fields et Values sont la liste des champs et des valeurs à modifier (facultatif).
VI-D-17. UpdateBatch▲
Met à jour toutes les modifications en attente (opération par lot). De la forme
recordset.UpdateBatch AffectRecords
Où AffectRecords définit les enregistrements concernés.
Si toutes les modifications échouent, une erreur se produit, s'il n'y a que quelques échecs, ils sont ajoutés à la collection Errors de la connexion.
VI-E. Événements▲
Pour pouvoir utiliser les événements ADO, il faut déclarer la variable précédée du mot clé WithEvents.
Les événements de l'objet Recordset sont tous appariés sauf un. Ce qui veut dire qu'il se produit un événement avant l'action concernée et un autre après. Ces événements sont principalement utilisés en programmation asynchrone.
VI-E-1. AdStatusEnum▲
Valeur que peut prendre le paramètre adStatus présent dans presque tous les événements.
Constante |
Valeur |
Description |
---|---|---|
adStatusOK |
1 |
Indique que l'opération qui a déclenché l'événement s'est passée avec succès |
adStatusErrorsOccurred |
2 |
Indique que l'opération qui a déclenché l'événement n'a pas pu se terminer correctement suite à une erreur |
adStatusCantDeny |
3 |
Indique qu'il est impossible d'annuler l'opération en cours |
adStatusCancel |
4 |
Une demande d'annulation a été demandée sur l'opération en cours |
adStatusUnwantedEvent |
5 |
Empêche de nouvelles notifications pendant le traitement d'un événement |
VI-E-2. EndOfRecordset▲
Private
Sub
Recordset_EndOfRecordset
(
fMoreData As
Boolean
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Se produit lorsque le recordset arrive en position EOF.
Où FMoreData définit s'il reste des enregistrements après. Doit être valorisé à « True » si pendant le traitement de l'événement on ajoute des enregistrements
AdStatus est l'état du recordset. Vaut adStatusOK si l'opération s'est bien passée et adStatusCantDeny si l'opération qui a déclenché l'événement ne peut être annulée. Si vous devez modifier le recordset pendant la procédure, ce paramètre doit être mis à adStatusUnwantedEvent afin de supprimer les notifications non désirées.
Precordset est la référence à l'objet subissant l'événement.
VI-E-3. FetchProgress et FetchComplete▲
Private
Sub
MonRs_FetchProgress
(
ByVal
Progress As
Long
, ByVal
MaxProgress As
Long
, _
adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Cet événement se déclenche périodiquement lors des opérations d'extractions asynchrones de longues durées. Les paramètres :
Progress représente le nombre de lignes extraites
MaxProgress le nombre de lignes qui doivent être extraites
Private
Sub
MonRs_FetchComplete
(
ByVal
pError As
ADODB.Error
, adStatus As
ADODB.EventStatusEnum
, _
ByVal
pRecordset As
ADODB.Recordset
)
Se produit après la récupération du dernier enregistrement.
Où PError est un objet erreur ADO
VI-E-4. WillChangeField et FieldChangeComplete▲
Private
Sub
MonRs_WillChangeField
(
ByVal
cFields As
Long
, _
ByVal
Fields As
Variant
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Private
Sub
MonRs_FieldChangeComplete
(
ByVal
cFields As
Long
, ByVal
Fields As
Variant
, _
ByVal
pError As
ADODB.Error
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Où cFields est le nombre de champs modifiés et Fields un tableau contenant ces champs.
La méthode WillChangeField est appelée avant qu'une opération en attente modifie la valeur d'un ou plusieurs objets Field dans le Jeu d'enregistrements. La méthode FieldChangeComplete est appelée après modification de la valeur d'un ou plusieurs objets Field.
Là il convient bien de ne pas se mélanger dans les événements. Ces événements se produisent lorsque la propriété value d'un ou plusieurs objets Field(s) est modifiée. Cela n'a rien à voir avec la transmission de valeur vers la base de données.
Pour annuler la modification, il suffit de mettre le paramètre adStatus à la valeur adStatusCancel dans l'événement WillChangeField.
VI-E-5. WillChangeRecord et RecordChangeComplete▲
Private
Sub
MonRs_WillChangeRecord
(
ByVal
adReason As
ADODB.EventReasonEnum
, _
ByVal
cRecords As
Long
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Private
Sub
MonRs_RecordChangeComplete
(
ByVal
adReason As
ADODB.EventReasonEnum
, _
ByVal
cRecords As
Long
, ByVal
pError As
ADODB.Error
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
La méthode WillChangeRecord est appelée avant qu'un ou plusieurs enregistrements dans le Recordset ne soient modifiés. La méthode RecordChangeComplete est appelée après qu'un ou plusieurs enregistrements sont modifiés.
adReason peut prendre les valeurs suivantes : adRsnAddNew, adRsnDelete, adRsnUpdate, adRsnUndoUpdate, adRsnUndoAddNew, adRsnUndoDelete, adRsnFirstChange ou adRsnFirstChange.
Ce paramètre indique l'action ayant provoqué le déclenchement de l'événement.
cRecords renvoie le nombre d'enregistrements modifiés.
Ces événements se produisent donc lorsqu'il y a modifications des recordset ou mise à jour des données. Ce sont des événements qui peuvent modifier ou annuler des modifications dans la base de données.
VI-E-6. WillChangeRecordset et RecordsetChangeComplete▲
Private
Sub
MonRs_WillChangeRecordset
(
ByVal
adReason As
ADODB.EventReasonEnum
, _
adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Private
Sub
MonRs_RecordsetChangeComplete
(
ByVal
adReason As
ADODB.EventReasonEnum
,_
ByVal
pError As
ADODB.Error
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
La méthode WillChangeRecordset est appelée avant qu'une opération en attente modifie le Recordset. La méthode RecordsetChangeComplete est appelée après que le Recordset a été modifié.
adReason peut prendre les valeurs suivantes : adRsnReQuery, adRsnReSynch, adRsnClose, adRsnOpen
Ces événements se produisent lors de remise à jour du recordset, ce sont des événements de recordset, ils n'influent jamais directement sur la base de données.
VI-E-7. WillMove et MoveComplete▲
Private
Sub
MonRs_WillMove
(
ByVal
adReason As
ADODB.EventReasonEnum
, _
adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
Private
Sub
MonRs_MoveComplete
(
ByVal
adReason As
ADODB.EventReasonEnum
, _
ByVal
pError As
ADODB.Error
, adStatus As
ADODB.EventStatusEnum
, ByVal
pRecordset As
ADODB.Recordset
)
La méthode WillMove est appelée avant que l'opération en attente change la position actuelle dans le Jeu d'enregistrements. La méthode MoveComplete est appelée après modification de la position actuelle dans le Recordset.
adReason peut prendre les valeurs suivantes : adRsnMoveFirst, adRsnMoveLast, adRsnMoveNext, adRsnMovePrevious, adRsnMove ou adRsnRequery
Attention à l'utilisation de ces événements. De nombreuses méthodes provoquent une modification de l'enregistrement en cours ce qui déclenche systématiquement cet événement. De plus il est très facile d'écrire un événement en cascade.