Programmer ADO Avec Delphi

download Programmer ADO Avec Delphi

of 122

Transcript of Programmer ADO Avec Delphi

PROGRAMMER ADO EN DELPHITABLE DES MATIERESTABLE DES MATIERES....................................................................................................1 INTRODUCTION................................................................................................................4 PREAMBULE ......................................................................................................................4 ADO: ACTIVEX DATA OBJECT ......................................................................................4 DEFINITION ........................................................................................................................4 Consommateur & fournisseur de donnes .......................................................................5 Fournisseur & composant de service ..............................................................................5 Jeu d'enregistrement (Recordset) ....................................................................................5 Proprits statiques & dynamiques (Properties) .............................................................6 MODELE OBJET ...................................................................................................................6 LA CONNEXION ...................................................................................................................6 Le fournisseur.................................................................................................................7 La source de donnes......................................................................................................7 Synchronisation ..............................................................................................................7 Erreurs ...........................................................................................................................7 Transactions...................................................................................................................8 Mode d'ouverture............................................................................................................8 LE RECORDSET (JEU D'ENREGISTREMENT) ...........................................................................9 Les Curseurs...................................................................................................................9 Mta-donnes ...............................................................................................................14 Donnes (Fields) ..........................................................................................................14 Mcanismes de base .....................................................................................................14 Modification d'un Recordset client................................................................................18 FIREHOSE, UN CURSEUR PARTICULIER ..............................................................................21 CONSEILS POUR CHOISIR SON CURSEUR.............................................................................22 SYNCHRONE VS ASYNCHRONE .........................................................................................22 OPERATION GLOBALE (PAR LOT).......................................................................................22 Les transactions............................................................................................................22 Les procdures stockes................................................................................................22 Gre par le code (traitement par lot) .............................................................................23 LE PIEGE "L'EXEMPLE JET"................................................................................................23 RECORDSET VS SQL.........................................................................................................24 RECORDSET PERSISTANT ..................................................................................................24 OPTIMISATION DU CODE ...................................................................................................24 L'optimisation dans l'accs aux donnes .......................................................................24 L'OBJET COMMAND ...........................................................................................................25 Communication vers le SGBD.......................................................................................25 Communication bidirectionnelle ...................................................................................25 Cration de requtes et de procdures ..........................................................................25 Collection Parameters ..................................................................................................25 TADOCONNECTION .........................................................................................................27 Proprits.....................................................................................................................27 Proprits dynamiques..................................................................................................30 Mthodes ......................................................................................................................32 Evnements...................................................................................................................35

1

TADOCOMMAND .............................................................................................................36 Proprits.....................................................................................................................36 Mthodes ......................................................................................................................39 OBJETS INCLUS: TBOOKMARK, TFIELD, TINDEXDEF ........................................................40 TBookmark ...................................................................................................................40 TField...........................................................................................................................40 TIndexDef.....................................................................................................................43 TADOQUERY ...................................................................................................................44 Proprits.....................................................................................................................44 Proprits dynamiques..................................................................................................51 Mthodes ......................................................................................................................54 Evnements...................................................................................................................60 TADOTABLE....................................................................................................................63 Proprits et mthodes spcifiques................................................................................63 TADODATASET ...............................................................................................................64 TADOSTOREDPROC .........................................................................................................64 EXEMPLES DE CODE .....................................................................................................65 NOMBRE D'ENREGISTREMENT ET POSITION .......................................................................65 COMPARAISON SQL VS RECORDSET ................................................................................66 RECHERCHE SUCCESSIVES OU DIRECTIONNELLES ..............................................................68 Les dfauts de la mthode Locate..................................................................................68 Gestion des signets .......................................................................................................69 Programmation intrinsque ..........................................................................................72 PROGRAMMATION ASYNCHRONE ......................................................................................74 Connection et command asynchrone .............................................................................75 Extractions bloquantes & non bloquantes .....................................................................76 Suivre l'extraction.........................................................................................................77 Gestion des modifications .............................................................................................77 RECORDSET PERSISTANT...................................................................................................78 SYNCHRONISATION...........................................................................................................79 GENERATION DE COMMANDES ..........................................................................................81 Les trois valeurs de TField............................................................................................81 Similaire au moteur de curseur.....................................................................................81 Commande paramtre.................................................................................................85 TRAITEMENT PAR LOT.......................................................................................................90 Gestion standard des erreurs ........................................................................................93 Actions correctives........................................................................................................95 Utiliser une transaction ................................................................................................95 ACCES CONCURRENTIEL ...................................................................................................96 Les procdures stockes................................................................................................97 Le verrouillage .............................................................................................................97 Transactions et exclusivit ............................................................................................98 CONCLUSION SUR ADO.................................................................................................98 ADOX: MICROSOFT ACTIVEX DATA OBJECTS EXTENSIONS .............................99 IMPORTER LA BIBLIOTHEQUE ADOX DANS DELPHI. .........................................................99 MODELE OBJET ...............................................................................................................100 RAPPELS ACCESS ............................................................................................................100 Scurit ......................................................................................................................100 Paramtrage JET........................................................................................................100 NOTIONS FONDAMENTALES ............................................................................................101 ADOX & Access .........................................................................................................101 Propritaire................................................................................................................101

2

ParentCatalog ............................................................................................................101 L'OBJET CATALOG ..........................................................................................................101 COLLECTIONS DE L'OBJET CATALOG...................................................................102 COLLECTION TABLES ......................................................................................................102 COLLECTION PROCEDURES .............................................................................................103 COLLECTION VIEWS .......................................................................................................103 COLLECTION GROUPS .....................................................................................................103 COLLECTION USERS........................................................................................................103 L'OBJET TABLE ...............................................................................................................103 Collection Properties..................................................................................................104 Collection Columns ....................................................................................................104 Objet Column .............................................................................................................105 COLLECTION INDEXES ....................................................................................................108 Objet Index.................................................................................................................108 COLLECTION KEYS .........................................................................................................109 Quelques notions ........................................................................................................109 Mthode Append.........................................................................................................110 Objet Key ...................................................................................................................110 Exemples ....................................................................................................................111 Conclusion sur les tables ............................................................................................113 L'OBJET PROCEDURE ......................................................................................................113 Cration d'un objet procdure.....................................................................................113 Modification d'un objet Procedure..............................................................................114 L'OBJET VIEW...............................................................................................................114 CONCLUSION SUR LES OBJETS VIEW & PROCEDURE ........................................................114 GESTION DES UTILISATEURS ...................................................................................114 CAS PARTICULIER D'ACCESS ...........................................................................................115 PROPRIETES ET DROITS ...................................................................................................115 Propritaire................................................................................................................115 Administrateur............................................................................................................115 Utilisateurs et groupes................................................................................................116 Hritage des objets .....................................................................................................116 OBJET GROUP .................................................................................................................116 SetPermissions............................................................................................................116 GetPermissions...........................................................................................................119 OBJET USER ...................................................................................................................120 ChangePassword ........................................................................................................120 GetPermissions & SetPermissions ..............................................................................120 Properties...................................................................................................................120 EXEMPLE ........................................................................................................................120 TECHNIQUES DE SECURISATION ......................................................................................121 Modification ...............................................................................................................122 Cration .....................................................................................................................122 Une autre solution : le DDL........................................................................................122 CONCLUSION SUR LA SECURITE.......................................................................................122 CONCLUSION.................................................................................................................122

3

INTRODUCTIONDans cet article nous allons regarder comment utiliser les accs des sources de donnes en utilisant ADO (ActiveX Data Object) et ADOX (extension pour la structure et la scurit) avec Delphi 7. Dans un premier temps nous dcouvrirons les technologies ADO ainsi que les concepts fondamentaux qu'il convient de connatre afin de les utiliser correctement. Dans la suite, nous verrons comment Delphi encapsule ces objets et permet de les mettre en uvre en utilisant les composants ou le code, enfin nous regarderons quelques exemples afin de dcouvrir quelques astuces. Pour ceux qui ont dj lu d'autres articles, que j'ai crit sur ADO pour VB, vous allez naviguer en terrain nouveau. En effet, du fait de l'encapsulation Delphi, la manipulation ADO est grandement modifie, je dirais mme amliore pour de nombreux points. S'il n'est pas possible d'utiliser ADO sans connatre ses principes fondamentaux, il est tout aussi vain d'essayer de le manipuler comme en VB ou en C++.

PREAMBULELorsqu'on est dans l'diteur Delphi, on est en droit de se demander quel peut bien tre l'intrt de connatre les mcanismes de fonctionnement d'ADO. Il est tout d'abord vident qu'il s'agit de l'attaque d'une base de donnes autre qu'Interbase. Dans le cas de base de donnes de type Access ou Sql-Server, la meilleure stratgie consiste utiliser les composants ADO intgrs dans Delphi depuis la version 6. Ils sont assez semblables aux contrles standards et on peut penser qu'il n'y a rien de plus connatre. Le petit exemple qui va suivre va vous montrer pourquoi un tel apprentissage est indispensable pour peu que l'on veuille faire autre chose que de la simple consultation. Imaginons une table de base de donnes contenant des doublons parfaits et n'ayant pas de contrainte d'unicit. Dans ma feuille, j'ajoute un composant TADOConnection dont je paramtre la proprit ConnectionString afin de me connecter la source de donnes, je cre un composant ADODataset (ou ADOTable) qui utilise cette connexion et au travers d'un composant DataSource, j'alimente un composant DBGrid. A l'excution, ma table apparat. Si je change une valeur de ma table dans une ligne qui n'est pas un doublon, pas de problme, la modification est rpercute dans la source de donnes. Par contre si cette ligne est un doublon, j'obtiens une erreur. Si je regarde mon composant ADODataset, il possde une proprit CursorLocation dont la valeur est clUseClient. En modifiant celle-ci la valeur clUseServer, mes modifications se font sans erreur quelle que soit la ligne modifie. Bien sur une telle table est aberrante, mais ADO comporte de nombreux piges que nous allons dcouvrir ensemble.

ADO: ActiveX Data ObjectDfinitionADO (ActiveX Data Object) est un modle d'objets dfinissant une interface de programmation pour OLE DB. OLE DB est la norme Microsoft pour l'accs universel aux donnes. Elle suit le modle COM (Component Object Model) et englobe la technologie ODBC (Open DataBase Connectivity) conue pour l'accs aux bases de donnes relationnelles. OLE DB permet un accs tout type de source de donnes (mme non relationnelles). OLE DB se compose globalement de fournisseurs de donnes et de composants de service.

4

Consommateur & fournisseur de donnesDans la programmation standard des bases de donnes, il y a toujours une source de donnes (dans le cas de cet article, une base Access exemple : biblio.mdb). Pour utiliser cette source de donnes, il faut utiliser un programme qui sait manipuler ces donnes, on l'appelle le fournisseur (dans certains cas serveur). Un fournisseur qui expose une interface OLE DB est appel Fournisseur OLE DB. Dans le cas qui nous intresse, votre code, qui demande des donnes est le consommateur (ou client). Attention, dans certains articles portant notamment sur les contrles dpendants vous pourrez trouver ces termes avec une autre signification. En effet, si vous liez des zones de champ (DBEdit) un contrle DataSource, le contrle DataSource sera (improprement) appel Fournisseur de donnes et vos zones de champs seront consommatrices. Pourquoi est-ce impropre ? Comme on ne voit pas le code que le contrle DataSource utilise pour demander des informations, on tend faire l'amalgame entre les deux. Mais c'est une erreur car le contrle est le consommateur de donnes. Nous verrons l'importance de cela avec les curseurs et le paramtrage des contrles de donnes.

Fournisseur & composant de serviceUn fournisseur de service permet d'ajouter des fonctionnalits au fournisseur de donnes. Il y en a plusieurs dans ADO tel que "Microsoft Data Shaping Service" qui permet la construction de jeux d'enregistrements hirarchiques ou "Microsoft OLE DB Persistence Provider" qui permet de stocker les donnes sous forme de fichiers. Un composant de service n'a pas d'existence propre. Il est toujours invoqu par un fournisseur (ou plus rarement par d'autres composants) et fournit des fonctionnalits que le fournisseur n'a pas. Dans cet article nous allons beaucoup parler du "Service de curseur pour Microsoft OLE DB" plus couramment appel moteur de curseur.

Jeu d'enregistrement (Recordset)Lorsque le fournisseur extrait des donnes de la source (requte SELECT), il s'agit de donnes brutes (sans information annexe) nayant pas un ordre particulier. Celles-ci ne sont pas trs fonctionnelles, et il faut d'autres informations pour pouvoir agir sur la source de donnes. En fait, un recordset (ou dataset) est un objet contenant des donnes de la base, agences de faon lisible, et des mta-donnes. Ces mta-donnes regroupent les informations connexes des donnes telle que le nom d'un champ ou son type et des informations sur la base telle que le nom du schma. Cette organisation est produite par un composant logiciel qui est le point central de la programmation ADO, le moteur de curseur. Le rsultat ainsi obtenu est appel curseur de donnes. Il y a dans ce terme un abus de langage qui explique bien des erreurs de comprhension. Le terme curseur vient de l'anglais "cursor" pour "CURrent Set Of Rows". On tend confondre sous le mme terme le moteur de curseur qui est le composant logiciel qui gre l'objet Recordset, l'objet Recordset (donnes, mta-donnes et interface) et enfin le curseur de donnes qui n'est rien d'autre que l'enregistrement en cours. Cet amalgame vient de l'objet Recordset qui contient la fois des informations destines au moteur de curseur, des donnes et des mthodes qui lui sont propres. Dans la suite de cet article comme dans la majorit de la littrature disponible, vous trouverez sous la dnomination "curseur" le paramtrage du jeu d'enregistrement vis vis du moteur de curseurs.

5

Proprits statiques & dynamiques (Properties)Dans le modle ADO et a fortiori dans le modle ADOX, de nombreux objets possdent une collection un peu particulire : "Properties". Celle ci concerne des proprits dites dynamiques par opposition aux proprits habituelles des objets (statiques). Ces proprits dpendent du fournisseur de donnes, elles ne sont en gnral accessibles qu'aprs la cration de l'objet (et ventuellement l'application d'une mthode refresh sur la collection) voire aprs l'ouverture de l'objet. On ne peut pas accder une proprit statique par l'intermdiaire de la collection Properties. Un objet Property dynamique comporte quatre proprits intgres qui lui sont propres, savoir : La proprit Name qui est une chane identifiant la proprit La proprit Type qui est un entier spcifiant le type de donne de la proprit. La proprit Value qui est un variant contenant la valeur de la proprit. La proprit Attributes qui est une valeur de type Long indiquant les caractristiques de proprits spcifiques au fournisseur.

Modle objetLe modle objet ADO est fondamentalement assez simple tel que nous le voyons dans le schma ci-dessous. Ce schma est volontairement incomplet. En effet dans le cadre de ce document nous n'tudierons pas les objets Record et Stream.

La connexionContrairement une ide reue, avec ADO, il y a toujours une connexion au moins lors de la cration des objets de donnes. Le fournisseur peut tre un fournisseur de donnes ou un fournisseur de service, la source de donnes peut tre distante ou locale, mais la connexion existe toujours. Elle peut tre soit explicite c'est dire dclare par votre code et/ou vos composants, soit implicite c'est dire cre par ADO. La connexion est une session unique d'accs une source de donnes et dans le cas d'application client/serveur elle reprsente aussi une connexion au rseau. Globalement une connexion attend toujours au moins deux lments, un fournisseur et une source de donnes. Le maintient de cette connexion active est souvent plus une question de ressource que de stratgie, comme nous le verrons dans l'tude du mode dconnect.

6

Le fournisseurADO en lui-mme n'est qu'une interface de haut niveau permettant d'utiliser OLE DB. La connexion doit donc imprativement dfinir le fournisseur utilis. Il appartient au dveloppeur de vrifier la prsence de ce fournisseur. N.B : Attention, certains empaquetages rcents du MDAC de Microsoft(2.6+) ne contiennent pas certains composants ou fournisseurs comme Microsoft Jet, le fournisseur Microsoft Jet OLE DB, le pilote Desktop Database Drivers ODBC ou le pilote Visual FoxPro ODBC. Pour pouvoir utiliser pleinement les fonctionnalits ADO, il convient d'installer aussi une version plus ancienne (habituellement la version 2.1). Le fournisseur peut tre dsign sous la forme d'un DSN (Data Source Name) ou sous son nom. Je n'utiliserai pas les DSN dans cet article attendu que je dconseille vivement leur utilisation. Dans la thorie ADO, il est conseill de dclarer le fournisseur le plus tt possible. En effet, vous avez remarqu que tous les objets ADO contiennent une collection "Properties". Celle-ci englobe ce que l'on appelle les proprits dynamiques de l'objet. En fait chaque objet ADO contient quelques proprits fixes, et de nombreuses proprits donnes par le fournisseur, ce qui sous-tend que ces proprits peuvent ne pas exister selon les fournisseurs. Elles ne sont donc pas accessibles tant que le fournisseur n'est pas dfini. Ces proprits peuvent parfois tre indispensables au bon fonctionnement du code.

La source de donnesLa connexion doit aussi contenir une rfrence la source de donnes. Il est vident que le fournisseur doit pouvoir manipuler cette source. Certaines sources peuvent tre accdes par plus d'un fournisseur. Nous verrons avec ADOX qu'il est possible de crer la source de donnes par le code.

SynchronisationUne connexion ADO peut tre synchrone ou non. Les connexions ADO n'imposent jamais d'tre synchrone, mais le dveloppeur peut les forcer tre asynchrones. Je m'explique, une connexion ADO est soit demande comme asynchrone, soit le fournisseur dcide. Il faut donc toujours bien garder l'esprit qu'une connexion peut ne pas tre toujours synchrone, selon la charge du serveur par exemple. De manire gnrale, il est moins lourd pour le serveur de traiter des connexions asynchrones.

ErreursLorsqu'une erreur ADO se produit, il y a ajout d'un objet "Error" la collection Errors de la connexion active de l'objet, si tant est que celle-ci existe encore. Une erreur rcuprable se produit galement. Une erreur classique consiste croire que la collection garde la trace de toutes les erreurs survenues lors de la session. En fait lorsqu'une erreur se produit, elle cre un ou plusieurs objets "Error" dans la connexion selon que l'erreur entrane d'autres erreurs en cascade ou non. Si une autre erreur survient par la suite, la collection est vide et le processus recommence. Certains passage de la programmation ADO comme la mise jour par lot de jeu d'enregistrement dconnect demande le traitement de ces erreurs (cf l'exemple Traitement par lot).

7

TransactionsIl s'agit l d'un vaste sujet, que nous allons survoler seulement pour l'instant. Pour plus de renseignement je vous conseille de lire : Les transactions par Henri Cesbron Lavau A quoi servent les transactions ? par frdric Brouard (SQLPro) L'utilisation des transactions est fortement recommande, car elles assurent une cohsion une suite de traitement nettement plus dur raliser avec le code client. D'autant plus qu'on peut imbriquer des transactions. Ceci permet de valider certaines modifications, tout en gardant la possibilit d'annuler l'ensemble la fin, l'inverse prsentant moins d'intrt. Dans certains cas, on peut remplacer les transactions par du code client, mais celui-ci doit tre gr comme une transaction. Comme vous l'avez lu dans l'article de Frdric, le point de difficult se situe autour de l'isolation. D'ailleurs, la grande difficult de la programmation des SGBD repose sur la gestion des accs concurrentiels. Il faut toujours suivre les rgles suivantes : v Tout risque de lecture sale est bannir v La transaction doit tre courte v Dans le doute, la transaction doit chouer. Notez enfin que certains fournisseurs ne grent pas tous les degrs d'isolation. Nous verrons dans les exemples, ce qu'il faut faire et ne pas faire

Mode d'ouvertureLorsqu'on ouvre une connexion ADO, on lui donne un certain nombre de privilges d'accs la source. L'exclusivit dfinit une connexion qui doit tre unique sur la source. Une telle connexion ne peut s'ouvrir s'il y a dj une connexion sur la source, et aucune autre connexion ne pourra avoir lieu sur une source ayant une telle connexion. L'exclusivit tant trs pnalisante, la connexion possde une proprit Mode qui dfinit soit ses propres droits soit qui restreint les droits des autres connexions ; tant bien entendu qu'une connexion restrictive peut restreindre les droits d'une connexion dj ouverte. Il convient donc d'tre vigilant lors de la restriction des droits.

8

Le recordset (jeu d'enregistrement)Les CurseursAvec ADO, impossible de parler de recordset sans parler du curseur de donnes qui va crer ce recordset. La quasi-totalit des problmes rencontrs lors de la programmation ADO sont dus un mauvais choix ou une mauvaise utilisation du curseur. Il faut dire la dcharge du dveloppeur que ceux-ci peuvent tre assez difficiles programmer, d'o l'ide de cet article. Schmatiquement le curseur doit grer deux sortes de fonctionnalits : v Celles propres la manipulation des donnes l'aide du recordset Comme je lai dj dit, les donnes renvoyes nont pas de notion denregistrement en cours ou de navigation entre enregistrements. Pour concevoir facilement lobjet Recordset il faut le voir comme une collection denregistrements. Cest le curseur qui permet de dfinir lenregistrement en cours et sil est possible daller ou pas vers nimporte quel autre enregistrement partir de lenregistrement en cours. Cest aussi lui qui permet de faire un filtrage, une recherche ou un tri sur les enregistrements du recordset. v La communication avec la source de donnes sous-jacente. Cette communication comprend plusieurs aspects tels que lactualisation des donnes du recordset, lenvoi de modifications vers la base de donnes, les modifications apportes par les autres utilisateurs, la gestion concurrentielle, etc. Malheureusement il n'y a pas une proprit pour chacune de ces fonctionnalits. En fait, ces fonctionnalits se dfinissent par la combinaison de deux proprits, le verrouillage (LockType) et le type du curseur (CursorType). Mais avant de dfinir ces proprits, il convient de choisir le positionnement du curseur et c'est l que commencent les problmes.

Positionnement (CursorLocation)Voil le concept qui fait le plus souvent dfaut. C'est pourtant un point fondamental. La position du curseur dfinit si les donnes du recordset sont situes dans le Process du client, c'est dire votre application ou dans celui du serveur, c'est dire celui du fournisseur. De plus le moteur du curseur et la bibliothque de curseur seront donns par le fournisseur si la position est ct serveur, alors qu'ADO invoquera le moteur de curseur client (composant de service) si la position est du ct client. La diffrence est primordiale car si vous n'avez pas vous proccuper du fonctionnement interne du fournisseur, il est utile de connatre le fonctionnement du moteur de curseur client. Nous verrons dans la discussion sur les curseurs clients tout ce que cela peut avoir d'important. La bibliothque de curseur dfinit aussi quelles fonctionnalits sont accessibles comme nous le verrons un peu plus loin. Certaines proprits / mthodes ne fonctionnent que si le curseur est du ct client et d'autres que s'il est du ct serveur. Nous verrons plus loin quand choisir l'un ou l'autre et pourquoi.

Curseur ct serveur (clUseServer)ADO utilise par dfaut des curseurs Serveurs (mais Delphi des curseurs clients). Ceux ci fournissent des recordset qui ont moins de fonctionnalits que leurs homologues clients, mais ayant les avantages suivants : Diminution du trafic rseau : Les donnes n'ayant pas transiter vers le client Economie des ressources du client puisque celui-ci ne stocke pas les donnes. Efficacit de mise jour. Comme c'est le fournisseur qui gre le recordset, celui-ci affiche les modifications en "temps rel" pour peu qu'un curseur ayant cette facult ait t demande. Facilit de programmation. Le fournisseur prenant en charge le curseur gre aussi directement les actions sur la source de donnes. Ils sont trs performants pour les petits recordset et les mises jour positionnes. Il faut par contre garder l'esprit : Que chaque client connect, va consommer des ressources ct serveur Que le nombre de connexions, ct serveur, n'est pas illimites La connexion doit constamment reste ouverte

9

Curseur ct client (clUseClient)Les curseurs ct client prsentent les avantages suivants : Nombreuses fonctionnalits ADO (tri, filtrage, recherche ) Une fois que les donnes sont dans le cache de votre application, celles-ci sont aisment et rapidement manipulables Possibilit de travailler hors connexion, voire de stockage sur le disque Par contre, ils prsentent deux inconvnients important : La surcharge de la connexion est facile atteindre, en cas de modifications frquentes des donnes Ils sont dlicats programmer comme vous allez avoir le plaisir de vous en rendre compte.

Fonctionnalits (bibliothque de curseur)Une fois dfinie la position, il vous faut choisir les fonctionnalits de votre recordset, et donc utiliser un des curseurs de la bibliothque. Un curseur se dfinit en valorisant les proprits LockType et CursorType de l'objet Recordset. Ces proprits doivent tre valorises avant l'ouverture du recordset. Le curseur va donc dfinir : Le dfilement L'accs concurrentiel L'actualisation des donnes du recordset Autant dire maintenant que le choix d'un mauvais curseur peut donner des comportements aberrants votre application. Pige n1 Lorsque vous demandez un curseur qui n'existe pas dans la bibliothque, le moteur ou le fournisseur vous en attribuera un autre n'ayant pas les mmes fonctionnalits sans toutefois dclencher d'erreur. Le choix de l'autre reste mes yeux un mystre, puisque la documentation dit "le curseur le plus proche".

Verrouillage (LockType)Le verrouillage (accs concurrentiel) est un lment indispensable des SGBD MultiUtilisateurs. Le verrouillage consiste interdire la possibilit a deux utilisateurs (ou plus) de modifier le mme enregistrement en mme temps. Il y a globalement deux modes de verrouillage :

Le verrouillage pessimiste (ltPessimistic)Pose un verrou sur les enregistrements ds que l'utilisateur tente de modifier une valeur (on dit l'dition). Le verrou dure jusqu' la validation des modifications. Si un enregistrement est dj verrouill, il se produit une erreur rcuprable lorsqu'un autre utilisateur tente de le modifier

Le verrouillage optimiste (ltOptimistic)Ce n'est pas un verrou stricto sensu, mais une comparaison de valeur. Selon les SGBD et aussi selon la structure de la table, la vrification se fait sur un numro de version, un champ date de modification (TimeStamp) ou la valeur des champs. Prenons un exemple avec les numros de version. Chaque recordset prend le numro de version de l'enregistrement. Lors de la validation d'un enregistrement, le numro de version change, toutes les modifications d'autres utilisateurs ayant alors un mauvais numro de version, celles-ci chouent. ADO supporte aussi un mode appel optimiste par lot (ltBatchOptimistic), qui marche comme expliqu ci-dessus quelques variations prs que nous verrons lors du traitement par lot. La proprit LockType accepte aussi un mode ReadOnly (ltReadOnly) qui interdit la modification des donnes du recordset

10

Quel verrou choisir?Les considrations de ce paragraphe seront sur les curseurs ct serveurs. La principale diffrence entre ces deux modes de verrouillage vient du comportement optimiste. En effet, un verrouillage pessimiste ne se proccupe pas de la version de l'enregistrement. Un enregistrement est ou n'est pas verrouill. S'il ne l'est pas rien n'empche plusieurs utilisateurs de modifier successivement le mme enregistrement. Dans le cadre d'un verrouillage optimiste il n'est thoriquement pas possible de modifier un enregistrement modifi par ailleurs. Cela est partiellement faux car sur un curseur qui reflte les modifications (KeySet par exemple), le numro de version sera remis jour chaque rafrachissement du Recordset. Le verrouillage optimiste ne sera donc que temporaire sur un curseur "dynamique". Ceci implique les observations suivantes : Le verrouillage pessimiste interdit les modifications simultanes sur un enregistrement mais pas les modifications successives. Le verrouillage optimiste peut n'tre que temporaire et risque de mal jouer son rle. Regardons le code ci-dessous : procedure TForm1.FormActivate(Sender: TObject); begin with ADOConnection1 do begin ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\biblio.mdb ;'; Connected:=true; ConnectionObject.Properties['Jet OLEDB:Page Timeout'].Value:=10000; end; with ADOQuery1 do begin SQL.Add('SELECT * FROM Authors'); Connection:=ADOConnection1; CursorLocation:= clUseServer; LockType:= ltOptimistic; CursorType:=ctKeyset; Active:=true; Edit1.Text:=fields[1].Value; end; end; procedure TForm1.Button1Click(Sender: TObject); begin with ADOQuery1 do begin Edit; fields[1].Value:=Edit1.Text; Post; end; end; J'ai modifi la valeur de la proprit dynamique "Jet OLEDB:Page Timeout" afin qu'il y ait 10 secondes entre chaque rafrachissement du recordset. Si j'excute deux instances de ce programme simultanment, je n'aurais jamais d'erreur si j'attends au moins 10 secondes entre chaque modification quelle que soit l'instance. Sinon, une erreur de verrouillage optimiste peut se produire. Comme souvent avec ADO, ces considrations peuvent forcer le choix du curseur. Par exemple, si vous voulez obtenir un verrouillage optimiste permanent avec MS-Jet, vous devez utiliser un curseur statique. Comme Jet ne vous fournira pas un curseur statique acceptant les modifications ct serveur, vous devrez utiliser un curseur ct client Le verrouillage pessimiste est configurable. Par dfaut, si on tente d'accder un enregistrement verrouill, il y aura dclenchement d'une erreur et la tentative d'accs chouera. Cependant on peut paramtrer la connexion, l'aide des proprits dynamiques "Jet OLEDB:Lock Delay" et "Jet OLEDB:Lock Retry" afin que la pose du verrou soit mise dans une boucle d'attente. Une telle boucle si elle empche le dclenchement d'une erreur peut facilement encombrer le serveur.

11

Type de curseur (CursorType)Dans cette proprit sont mles le dfilement et la sensibilit aux modifications des donnes. Le dfilement est une fonctionnalit du curseur. Elle reprsente la facult qu'a le jeu d'enregistrement de reflter la position de l'enregistrement en cours, ainsi que sa facult organiser et se dplacer dans le jeu de donnes. La sensibilit aux donnes reprsente la facult qu'a le recordset de reflter les modifications, ajouts, suppressions effectus sur les donnes. Je vais vous prsenter ces curseurs en prcisant chaque fois leurs fonctionnalits iPar position, on entend la possibilit de dterminer la position de l'enregistrement en cours au sein du jeu d'enregistrements. Il existe quatre types de curseur :

En avant seulement (ctOpenForwardOnly)Position Non Dfilement En avant Sensibilit Pas de mise jour des donnes modifies certaines, seuls les enregistrements non accds seront mis jour. Ce type de curseur est le plus rapide. Idal pour la lecture de donnes en un seul passage.

Statique (ctStatic)Position Oui Dfilement Bidirectionnel Sensibilit Pas de mise jour des donnes modifies Copie de donnes. Les curseurs ct client sont toujours statiques.

Jeu de cl (ctKeyset)Position Oui Dfilement Bidirectionnel Sensibilit Reflte les modifications de donnes mais ne permet pas de voir les enregistrements ajouts par d'autres utilisateurs Demande d'tre utiliser avec des tables indexes. Trs rapide car il ne charge pas les donnes mais juste les cls.

Dynamique (ctDynamic)Position Oui Dfilement Bidirectionnel Sensibilit Reflte toutes les modifications de donnes ainsi que les enregistrements ajouts ou supprims par d'autres utilisateurs Le poids lourd des curseurs. N'est pas support par tous les fournisseurs.

HritageLa cration d'un objet Recordset sous-entend toujours la cration d'un objet Connection et d'un objet Command. Soit on cre ces objets de faon explicite soit ils sont crs par ADO de faon implicite lors de l'ouverture du recordset. La cration implicite pose deux problmes : Ces objets cessent d'exister lors de la fermeture du Recordset et doivent tre rcrs chaque excution et on multiplie ainsi le nombre de connexion la base. On oublie de paramtrer correctement ces objets, voire on oublie qui plus est qu'on les crs, mais le recordset hritant de certaines de leurs proprits, on n'obtient pas ce que l'on dsire. Ces deux objets se retrouvent dans les proprits Connection et Command de l'objet DataSet. Cet hritage est important comme nous allons le voir dans la suite de cet article. Un jeu d'enregistrement dont la proprit Connection vaut Nil et utilisant un curseur client est un jeu d'enregistrement dconnect, un jeu d'enregistrement dont la proprit ActiveCommand vaut Nil est dit "Volatile".

12

Taille du cacheRgler la taille du cache peut tre important pour l'optimisation des curseurs serveurs. En fait, lorsque vous demandez un jeu d'enregistrement au fournisseur de donnes, celui-ci n'est pas forcment compltement rapatri dans l'espace client. Vous pouvez dfinir le nombre d'enregistrements qui seront transmis chaque fois en rglant la proprit CacheSize de l'objet DataSet. Ce rglage ce fait en donnant le nombre d'enregistrements que le cache peut accepter dans la proprit CacheSize. S'il y a plus d'enregistrements retourns qu'il n'y a de place dans le cache, le fournisseur transmet uniquement la quantit d'enregistrements ncessaire pour remplir le cache. Lors de l'appel d'un enregistrement ne figurant pas dans le cache, il y a transfert d'un nouveau bloc d'enregistrements. Ce mode de fonctionnement implique toutefois un pige. Lors des rafrachissements priodiques de votre recordset (dynamique ou KeySet), les enregistrements du cache ne sont pas rafrachis. Il faut forcer celui-ci en appelant la mthode Resync. Il n'y a pas de rgles absolues pour dire qu'elle taille de cache il faut utiliser. Je n'ai pour ma part pas trouv d'autres mthodes que de faire des tests selon les applications.

Etat, statut et dplacementLa notion d'tat et de statut est toujours un petit peu complexe apprhender. Un jeu d'enregistrement ADO possde un tat (ouvert, ferm, en cours, etc) et un statut qui lui correspond son mode (dition, navigation, filtrage.). L'tat est propre au jeu d'enregistrement tandis que le statut peut lui dpendre du statut de l'enregistrement en cours. L'enregistrement courant possde uniquement un statut (erreur, nouveau, supprim, etc). Il peut subir des changements d'tat mais il les transmet toujours au statut du jeu d'enregistrements auquel il appartient. Normalement un changement d'tat est toujours du un appel explicite d'une mthode de changement d'tat (Filtered, Edit). Mais il convient de se mfier car certaines de ces mthodes induisent l'appel d'autres mthodes qui elles sont masques, c'est le cas des changements de position courante. Lorsque l'enregistrement courant est en mode d'dition, le changement de position va valider les modifications en cours sans appel explicite de la mthode Post. Cela est du la transmission de l'tat de l'enregistrement vers le statut du jeu de donnes. Je vais dtailler quelque peu car les explications de l'aide sont un peu confuses. Prenons l'exemple suivant: adoRecordset:=TADOQuery.Create(Owner); with adoRecordset do begin ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\biblio.mdb;'; CursorLocation:=clUseClient; CursorType:=ctStatic; LockType:=ltOptimistic; SQL.Add('SELECT * FROM Authors'); Active:=True; First; Edit; FieldValues['year born']:=1947; MoveBy(1); end; Que se passe-t-il dans ce cas l ? Lors de l'appel de la mthode First, le statut du jeu d'enregistrement est en navigation, le statut de l'enregistrement courant est 'UnModified'. A l'appel de la mthode Edit il y a basculement de l'enregistrement et donc du jeu d'enregistrement en mode Edition. Le statut de l'enregistrement n'a pas encore t modifi. Lors du changement de la valeur, le statut de l'enregistrement change (Modified). Tout se passe lors de l'appel de la mthode MoveBy. Le jeu d'enregistrement vrifie s'il est en statut de navigation, c'est dire qu'il invoque la mthode CheckBrowseMode. Cette mthode vrifie le

13

statut de l'enregistrement en cours. Si celui-ci est diffrent du UnModified, la mthode Post est alors appele, le statut de l'enregistrement change de nouveau et le jeu d'enregistrements bascule dans le mode navigation. Vous voyez bien, que la validation des modifications peut tre induite. Nanmoins une programmation vnementielle peut permettre un contrle sur ce genre de phnomnes.

Mta-donnesLe recordset donc besoin pour fonctionner de donnes autres que celles renvoys par la requte, a fortiori si vous allez modifier la base par l'intermdiaire de ce recordset. Ces mta-donnes se divisent en deux blocs, celles qui sont stockes dans les proprits statiques et dynamiques des objets Fields, et celles qui sont stockes dans la collection des proprits dynamiques de l'objet Recordset. Celles stockes dans les proprits statiques des objets Fields sont les mmes quelle que soit la position du curseur. Par contre, les proprits dynamiques de l'objet recordset, ainsi que la collection Properties de chaque objet Field, sont trs diffrentes selon la position du curseur. Si on compare un recordset obtenu avec un curseur ct client de son homologue ct serveur, on constate qu'il possde beaucoup plus de proprits dynamiques, alors que le second est le seul possder la srie des proprits "Jet OLE DB". Ceci vient de la diffrence fondamentale de comportement du curseur. Lorsqu'on invoque un curseur ct serveur, le fournisseur OLE DB prend en charge la gestion de ce curseur. Il valorise quelques proprits dynamiques qui lui sont propres, mais le recordset n'a pas besoin de stocker des informations de schma puisque c'est le fournisseur qui va agir sur la base de donnes. Il ne faut pas confondre ce fonctionnement avec l'appel Delphi des mta-donnes (GetTableNames, GetFieldNames, etc) qui est li un appel spcifique de l'objet Connection (quivalent l'appel de OpenSchema ADO).

Donnes (Fields)Pour stocker les donnes de la requte, les recordset possdent une collection Fields. Chaque objet Field reprsente un champ invoqu par la requte SELECT ayant cre le recordset. Un objet Field comprend : La valeur de la donne de l'enregistrement en cours. En fait, la valeur apparat trois fois. La proprit Value contient la valeur existante dans votre Recordset, la proprit UnderlyingValue contient la valeur existante dans la source de donnes lors de la dernire synchronisation enfin la proprit OriginalValue contient la valeur de la base lors de la dernire mise jour. Nous allons voir plus loin tout ce que cela permet et induit. Les mta-donnes du champ (nom, type, prcision). Elles sont disponibles avant l'ouverture du recordset si la connexion est dj dfinie dans l'objet Recordset et si la proprit source contient une chane SQL valide, sinon on ne peut y accder qu'aprs l'ouverture du recordset. Les informations de schma. Elles se trouvent dans la collection Properties de l'objet Field. Elles existent toujours quel que soit le ct du curseur, mais il y en a plus du ct client. Attention, ces informations peuvent tre fausses si le moteur de curseur n'en a pas besoin, pour un recordset en lecture seule par exemple. Les objets Field ADO ne sont pas encapsuls dans Delphi. Il convient de ne pas confondre les champs ADO avec les objets champs fournis par Delphi.

Mcanismes de baseNous avons maintenant le minimum requis pour comprendre ce qui se passe lors de la manipulation d'un objet Recordset. Je rappelle ici ce point fondamental, l'utilisation des proprits dynamiques des objets ADO demande toujours la dfinition du fournisseur. En clair, la proprit Provider doit tre dfinie pour utiliser les proprits dynamiques de l'objet Connection, et la proprit Connection doit tre valorise pour utiliser les collections Properties des objets Command et Recordset.

14

Nous allons regarder maintenant quelques oprations courantes sur un recordset pour voir ce qui se passe au niveau du moteur de curseur. Ces exemples seront principalement dans le cadre des curseurs clients, puisque le fonctionnement des recordset ct serveur est gr par le fournisseur de donnes. Dans le cadre de Delphi je ne vais utiliser dans cette partie que les composants TADOConnection, TADOQuery et TADOCommand.

Cration du jeu d'enregistrementGnralement, pour ouvrir un jeu d'enregistrement, quelle que soit la mthode utilise, vous allez consciemment ou non envoyer une requte SQL SELECT au fournisseur de donnes. Il est nullement ncessaire d'avoir la moindre connaissance de la structure de la base, pour peu que celle-ci possde des requtes stockes (Vues), nanmoins on connat en gnral le schma de la source (au moins superficiellement). Fondamentalement, les diffrences de fonctionnement commencent lors de l'appel de la mthode Open, mais souvent pour des raisons de marshaling, tout se passe ds le paramtrage de l'objet. Examinons le code suivant : with ADOConnection1 do begin ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\biblio.mdb ;'; Connected:=true; end; with ADOQuery1 do begin Connection:=ADOConnection1; SQL.Add('SELECT * FROM Authors'); CursorLocation:= clUseClient; LockType:= ltOptimistic; CursorType:= ctStatic; Active:=true; Edit1.Text:=fields[1].Value; end; Si j'espionne le recordset avant l'appel de la mthode Open, je vois que quelques proprits dynamiques (informations de schma) et toutes les proprits statiques (mta-donnes) des objets Field du recordset sont correctement valorises quelle que soit la position du curseur. La raison est simple, ADO a envoy une requte de rcupration de schma lors de l'affectation de la proprit SQL. Avec un curseur ct serveur, la requte de schma valorise les mta-donnes de l'objet recordset (serveur) puis un pointeur d'interface est transmis vers l'application cliente. Dans le cas du curseur client, le moteur de curseur transfere un recordset contenant les mta-donnes vers l'objet Recordset qui est situ dans l'espace client. Il y une diffrence importante de temps de traitement entre les deux, alors que le volume des mta-donnes transmis est trs faible. Il va y avoir ensuite une diffrence encore plus importante lors de l'appel de la mthode Open. Ct serveur, le fournisseur excute la requte et transmet les enregistrements ncessaires au remplissage du cache. Ce traitement peut tre encore acclr avec un curseur jeu de cl (Key set) puisque celui ci ne valorise qu'un jeu de cl. Le moteur de curseur ct client va par contre devoir rcuprer les valeurs de la source renvoyes par la requte et les transmettre vers le recordset de l'espace client. Ceci tant fait, comme le paramtrage prcise que le Recordset doit tre modifiable (Updatable), il va renvoyer une requte de schma, videmment diffrente de la premire, afin de rcuprer les informations ncessaires aux actions ventuelles sur la source de donnes. Comme nous le voyons, la construction d'un recordset client est assez lourd, surtout si la requte doit renvoyer des milliers d'enregistrements.

15

Action sur le recordsetQue va-t-il se passer lorsqu'on fait une modification sur l'objet recordset ? Pour bien comprendre l'influence de la position du curseur je vais reprendre mon exemple du dbut avec une table sans cl, contenant des doublons parfaits (lignes dont toutes les valeurs sont identiques). Excutons le code suivant procedure TForm1.FormActivate(Sender: TObject); begin with ADOConnection1 do begin ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\user\jmarc\bd6.mdb;'; Connected:=true; end; with ADOQuery1 do begin SQL.Add('SELECT * From TabSansCle'); Connection:=ADOConnection1; CursorLocation:= clUseServer; LockType:= ltOptimistic; CursorType:=ctKeyset; Active:=true; //Recordset.Find('nom = ' + QuotedStr('bb'),0, 1, 1); // Locate('nom','bb',[]); Edit; //Recordset.Fields('numer').Value:=21; // FieldByName('numer').Value:=21; Post; end; end; Dans ma table j'ai plusieurs enregistrements dont le nom est "bb", certains d'entre eux tant des doublons parfaits. Si je regarde ma base aprs excution, je constate qu'un de mes enregistrements pris 21 pour valeur "numer". Maintenant j'excute le mme code en positionnant ct client le recordset. A l'appel de la mthode Update, j'obtiens l'erreur "80004005 : Informations sur la colonne cl insuffisantes ou incorrectes ". Ce petit exemple permet de dmontrer la diffrence de fonctionnement entre les curseurs clients et serveurs. Dans le cas de l'opration ct serveur, c'est le fournisseur qui gre le curseur. Le fournisseur sait localiser physiquement l'enregistrement en cours du recordset dans la source de donnes et peut donc procder la modification. Par contre, lorsqu'on procde du ct client, le moteur de curseur doit crire une requte action pour le Fournisseur. Dans notre cas, le curseur ne trouve pas dans les mta-donnes de cl primaire pour la table (puisque la table n'en contient pas) ni d'index unique. Il se trouve donc dans l'impossibilit d'crire une requte action pertinente, puisqu'il ne peut pas identifier l'enregistrement en cours, ce qui provoque la gnration de l'erreur dont pour une fois le message est tout fait explicite. Dans ce cas prcis, le curseur porte mal son nom puisqu'il existe un enregistrement en cours dans le recordset, mais qu'il ne peut pas tre identifier pour agir dessus. Nanmoins j'ai pris l un cas extrme, la limite d'tre absurde. Dans le cas des recordset ct client, il y a toujours tentative de construction d'une requte action pour traduire les modifications apportes l'objet Recordset. N.B : J'ai mis en commentaire une autre syntaxe de recherche base sur la recherche ADO. Dans ce cas je devrais appeler diffremment la valeur du champ (deuxime ligne de commentaire) pour que le fonctionnement soit correct. Nous verrons cela plus en dtail dans la deuxime partie.

16

Echec ou russiteIl est important de comprendre comment le curseur va ragir lors de l'chec ou de la russite d'une action. Le moteur de curseur (client ou serveur) utilise les mta-donnes stockes dans le recordset pour valider une opration sur un recordset. Ce contrle lieu en deux temps : q Lors de l'affectation d'une valeur un champ La valeur saisie doit respecter les proprits de l'objet Field concern. Vous aurez toujours un message d'erreur si tel n'est pas le cas, mais vous n'aurez pas le mme message selon la position du curseur. Si par exemple vous tentez d'affecter une valeur de type erron un champ, vous recevrez un message d'incompatibilit de type pour un curseur Serveur, et une erreur Automation pour un curseur client. q Lors de la demande de mise jour Indpendamment de la position lorsqu'il y a un chec, une erreur standard est leve et il y a ajout d'une erreur la connexion dfinie dans la proprit Connection de l'objet DataSet. La proprit Status de l'enregistrement concern prendra une valeur cense reflter la cause de l'chec. L encore, la pertinence de cette valeur va varier selon la position du curseur. Dans une opration ct serveur, si dans un accs avec verrouillage optimiste je cherche modifier une valeur d'un enregistrement qui vient d'tre modifie par un autre utilisateur, j'obtiendrais une erreur "signet invalide" puisque le numro de version ne sera plus le bon. Dans la mme opration ct client, il y aura une erreur "violation de concurrence optimiste". Le pourquoi de ces deux erreurs diffrentes pour une mme cause va nous amener comprendre comment le moteur de curseur du client construit ses actions. En cas de russite de la modification, l'opration est marque comme russie (dans la proprit Status) et il y a alors synchronisation.

SynchronisationLa synchronisation est l'opration qui permet de mettre jour le jeu d'enregistrement avec les donnes de la source de donnes sous-jacente. La synchronisation est normalement explicite, c'est dire demande par l'utilisateur l'aide de la mthode Resync, mais elle suit aussi une opration de modification des donnes, elle est alors implicite. v Synchronisation explicite Elle peut porter sur tout ou partie d'un recordset ou sur un champ. Il existe deux stratgies diffrentes selon que l'on dsire rafrachir l'ensemble du recordset ou juste les valeurs sousjacentes. Dans le premier cas, toutes les modifications en cours sont perdues, dans l'autre on peut anticiper la prsence de conflits. v Synchronisation de modification Elle est plus complexe apprhender. Elle suit les rgles suivantes : Elle porte uniquement sur les enregistrements modifis dans votre recordset Les champs sur lesquels la valeur a t modifie sont toujours synchroniss Sur un recordset ct serveur, la synchronisation qui suit une opration sur les donnes et toujours automatique et non paramtrable. Elle porte sur tous les champs de l'enregistrement modifi. Par contre du ct client il est possible de spcifier le mode de synchronisation l'aide de la proprit dynamique "Update Resync". N'oublier pas la rgle d'or, les champs modifis d'une opration russie mettent la nouvelle valeur de la base dans leur proprit OriginalValue.

17

Modification d'un Recordset clientCe que nous allons voir maintenant est propre aux curseurs ct client. Rappelez-vous que la gestion des jeux d'enregistrements ct serveurs est faite par le fournisseur de donnes et qu'il n'est donc pas la peine de se pencher sur ce fonctionnement en dtail. Lors d'une modification des donnes de l'objet Recordset, le moteur de curseur va construire une ou plusieurs requtes action permettant de transmettre les modifications de l'objet Recordset vers la source de donnes. En SQL, il n'existe que trois types de requtes action pour manipuler les donnes, de mme, il n'existe que trois mthodes de modification des donnes d'un recordset. Dans la suite de ce chapitre, nous regarderons l'application de traitement direct, les traitements par lots reposant sur le mme principe (en ce qui concerne les requtes SQL). Si vous tes tanche au SQL, le passage qui suit va vous sembler abscons. Je vous engage alors commencer par consulter l'excellent cours de SQLPRO.

Modification (Update)Commenons par un exemple simple. with ADOConnection1 do begin ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\biblio.mdb;'; Connected:=true; end; with ADOQuery1 do begin SQL.Add('SELECT * From Authors'); Connection:=ADOConnection1; CursorLocation:= clUseClient; LockType:= ltOptimistic; CursorType:= ctStatic; Active:=true; Locate('Author','Gane, Chris',[]); Edit; FieldByName('year born').Value:=1941; Post; end; Lors de l'appel de la mthode Update, le moteur de curseur va construire une requte SQL UPDATE pour appliquer la modification. Par dfaut le modle de la requte est de la forme UPDATE Table SET Champs modifis=recodset.fields(Champs modifis).Value WHERE champs cls= recodset.fields(Champs cls).OriginalValue AND champs modifis= recodset.fields(Champs modifis).OriginalValue AND ventuelle condition de jointure Donc dans l'exemple que j'ai pris, la requte transmise par le moteur de curseur au fournisseur OLE DB sera : UPDATE Author SET [year born] = 1941 WHERE Au_Id = 8139 AND [year born] = 1938 Comment le moteur de curseur fait-il pour construire cette requte ? Il va chercher pour chaque champ modifi la table correspondante, cette information tant toujours disponible dans la collection properties de l'objet Field correspondant, puis il va rcuprer dans les mta-donnes la cl primaire de la table. Avec ces informations, il va construire sa requte sachant que les valeurs utilises dans la clause WHERE sont toujours tires des proprits OriginalValue des objets Fields de l'enregistrement en cours.

18

Si d'aventure vous n'avez pas inclus le(s) champ(s) constituant la cl primaire, il est possible que le moteur ait quand mme rcupr cette information. Si telle n'est pas le cas ou si votre table ne possde pas de cl primaire, le moteur lancera une requte d'information pour trouver un ventuel index unique lui permettant d'identifier de manire certaine l'enregistrement courant. Si cela s'avre impossible, vous obtiendrez une erreur comme nous l'avons vu plus haut. Il faut donc toujours veiller lors de l'utilisation d'un curseur client donner les informations ncessaires au moteur de curseur si on dsire effectuer des modifications de donnes. Cette requte est ensuite transmise au fournisseur OLE DB. Celui-ci retourne en rponse au moteur de curseur le nombre d'enregistrements affects. Si celui ci est gal zro, il y a dclenchement d'une erreur, sinon l'opration est marque comme russie. Il y a alors synchronisation de l'enregistrement. Tout a l'air parfait mais il y a une faute de verrouillage. En effet, s'il y a eu modification ou verrouillage de l'enregistrement par un autre utilisateur, ce n'est pas stricto sensu par le changement de numro de version du verrouillage optimiste que la requte choue mais parce que les valeurs stockes dans les proprits OriginalValue ne permettent plus d'identifier l'enregistrement en cours. Or cela peut tre trs diffrent. Imaginons le scnario suivant, dans le temps entre la cration du recordset et l'appel de la mthode Update, un autre utilisateur a chang le nom en "Gane, Peter". Normalement, du fait du verrouillage, la modification de la date de naissance devrait chouer, pourtant il suffit de lire le code SQL correspondant pour voir qu'elle va russir, puisque le champ 'Author' n'apparat pas dans la clause WHERE. Pour viter ce problme ou pour contourner d'autres limitations, on peut paramtrer les rgles de construction de la requte action du moteur de curseur l'aide de la proprit dynamique "Update Criteria". Il y a aussi un danger si on fait l'amalgame entre ADO et SQL. Avec une requte SQL de modification je peux m'affranchir de la valeur originelle du champ. Par exemple la requte SQL suivante est valide : UPDATE Author SET [year born] = [year born] + 1 WHERE Au_Id = 8139 Mais du fait de la concurrence optimiste elle ne peut pas tre excute par le moteur de curseur ADO avec un code comme celui ci-dessous : Locate('Author','Gane, Chris',[]); Edit; FieldByName('year born').Value:=FieldByName('year born').Value+1; Post; Ce code ne fonctionnera que si la valeur du champ [year born] dans la base est la mme que celle prsente

Suppression (DELETE)Ce sont ces requtes qui posent le moins de problmes avec ADO. Dans ce cas, la requte n'utilisera que le(s) champ(s) composant la cl primaire pour crire la requte Delete SQL. Locate('Author','Gane, Chris',[]); Delete; Sera transform par le moteur en : DELETE FROM Authors WHERE Au_Id = 8139 L pas de problme de critre ou de synchronisation. NB : Dans le cas de la base biblio, une erreur sera dclenche puisqu'il y aurait tentative de suppression en cascade

Ajout (INSERT INTO)Ces requtes vont nous permettre de comprendre le principe de la synchronisation. Une remarque s'impose au pralable. Ne tentez pas d'entrer une valeur dans un champ valeur automatique

19

(NumeroAuto ou TimeStamp), vous obtiendrez alors une erreur systmatique. De mme, donnez des valeurs tous les champs ne pouvant tre NULL avant d'appeler la mthode Update. Prenons un exemple : var Recup:integer; begin with ADOConnection1 do begin ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\biblio.mdb;'; Connected:=true; end; with ADOQuery1 do begin SQL.Add('SELECT * From Authors'); Connection:=ADOConnection1; CursorLocation:= clUseClient; LockType:= ltOptimistic; CursorType:=ctStatic; Active:=true; //recordset.Properties['Update Resync'].Value:=1; Insert; FieldByName('Author').Value:='RABILLOUD, Jean-Marc'; FieldByName('year born').Value:=1967; Post; Edit1.Text:=FieldByName('Au_Id').AsString; end; end; Comme vous le voyez, je n'entre pas de valeur pour le champ "Au_Id" puisqu'il s'agit d'un champ NumeroAuto. La requte action crite par le moteur de curseur sera : INSERT INTO Authors (Author, [year born]) VALUES ("RABILLOUD , Jean-Marc",1967) La requte ne contient pas de valeur pour le champ "Au_Id" celle-ci tant attribue par le SGBD. Jusque l pas de problme. Mais que va-t-il se passer si j'ai besoin de connatre cette valeur dans la suite de mon code. Il me suffit d'crire : Recup :=FieldByName('Au_Id').Value Bien que je n'aie pas spcifi le mode de mise jour(ligne en commentaire), la valeur par dfaut de synchronisation est "adResyncAutoIncrement" (1) et le code fonctionne. Attention, ce code ne fonctionnera pas avec une version d'ADO infrieure 2.1 ni avec un fournisseur tel que JET 3.51. Cela fonctionne car le moteur de curseur envoie des requtes complmentaires afin de mettre jour le nouvel enregistrement. Cela ne fonctionnera pas avec Jet 3.51 car il ne supporte pas la requte SELECT @@IDENTITY qui permet de connatre le nouveau numro attribu, et sans celui-ci il n'est pas possible pour le moteur de curseur d'identifier l'enregistrement nouvellement cr. Pour connatre les possibilits de paramtrage de la mise jour, allez lire le paragraphe Proprits dynamiques - "Update Resync" de l'objet TADOQuery.

Requte avec jointureJusque l, nous avons regard des cas simples ne portant que sur une seule table, mais dans les autres cas, cela peut tre nettement plus compliqu. Imaginons la requte suivante : SELECT * FROM Publishers, Titles WHERE Publishers.PubID = Titles.PubID Note SQL : Il est videmment plus logique d'crire une requte avec INNER JOIN, mais dans ce chapitre je vais faire mes jointures dans la clause WHERE afin de garder une criture cohrente avec le moteur de curseur. J'utilise le code suivant : with ADOQuery1 do begin 20

SQL.Add('SELECT * FROM Publishers, Titles WHERE Publishers.PubID = Titles.PubID'); Connection:=ADOConnection1; CursorLocation:= clUseClient; LockType:= ltOptimistic; CursorType:=ctStatic; Active:=true; Locate('Title','Evaluating Practice',[]); Edit; FieldByName('Name').Value:='ALPHA BOOKS'; FieldByName('Title').Value:=FieldByName('Title').Value+'s'; Post; end; Pour rsumer, je recherche le livre dont le titre est 'Evaluating Practice' je veux changer son diteur, par un autre diteur existant dans la base et ajouter un 's' au titre du livre. Bien sur, vue comme cela, la technique l'air un peu branlante, mais c'est exactement ce que 95% des utilisateurs essayent de faire de manire transparente avec un Datagrid par exemple. Que va-t-il se passer si vous excutez ce code? Le moteur de curseur va crire autant de Requte action que de table concerne par les modifications dans notre cas : UPDATE Publishers SET Name = 'ALPHA BOOKS' WHERE PubId = 129 AND Name = 'ALLYN & BACON' et UPDATE Titles SET Title = 'Evaluating Practices' WHERE ISBN = '0-1329231-8-1' AND Title = 'Evaluating Practice' Comme vous le voyez, ce n'est pas ce que nous voulions obtenir puisque l'diteur 'ALLYN & BACON' a disparu de la base. La faute est norme puisqu'il faut modifier la cl trangre pour obtenir ce que nous voulons mais nous voyons que le moteur de curseur ne peut pas grer ce style de programmation. Dans ce cas pourtant, il existe des proprits dynamiques qui permettent de contourner le problme. En effet vous pouvez dfinir l'aide de la proprit "Unique Table", une table sur laquelle porteront les modifications dans une requte avec jointure, et l'aide de la proprit "Resync Command" un mode de synchronisation pour ces mmes requtes. Pour voir leur utilisation, lisez l'exemple "proprits dynamiques Resync Command" du prsent cours.

FireHose, un curseur particulierPar dfaut, le curseur fournit cot serveur est un curseur "FireHose" qui a les caractristiques suivantes : Ct serveur En avant seulement Lecture seule Taille du cache=1 Ce type de curseur est le plus rapide. Il possde une particularit dont il convient de se mfier. Ce curseur est exclusif sur sa connexion, ce qui revient dire que la cration d'un autre recordset utilisant la mme connexion engendre la cration d'une connexion implicite. Encore pire, si vous fermer votre recordset avant d'avoir atteint la position EOF, la connexion sera toujours considre comme tant utilise. Il convient donc de faire attention avec ce type de curseur. Attention bien que la mthode MoveLast provoque un mouvement vers l'avant, elle dclenche une erreur sur les curseurs "En avant seulement".

21

Conseils pour choisir son curseurEn suivant les rgles donnes ci-dessous vous ne devriez pas vous tromper souvent. Nanmoins ces rgles ne sont pas intangibles et dans certains cas il vous faudra procder votre propre analyse pour dterminer le curseur ncessaire. v Certaines proprits/mthodes ne fonctionnent qu'avec un curseur d'un ct spcifique, si vous avez besoin de celles-ci, utilisez le curseur correspondant. v Les fournisseurs ne donnent pas accs toutes les combinaisons possibles. Etudiez d'abord les curseurs que le fournisseur peut mettre disposition v Sur une application ou le SGBD est sur la machine du client et qui ne peut avoir qu'un utilisateur simultan, on utilise toujours un curseur ct serveur. v Si vous devez modifier des donnes (mise jour, ajout, suppression) utilisez plutt un curseur ct serveur. v Si vous devez manipuler un gros jeu d'enregistrement, utilisez un curseur ct client. v Privilgiez toujours Les curseurs en avant s'ils sont suffisants Les curseurs en lecture seule v Pour les applications Multi-Utilisateurs Verrouillez en mode pessimiste les curseurs ct serveur Travaillez par lot sur les curseurs ct clients avec des transactions v Prfrez toujours l'utilisation du SQL par rapport aux fonctionnalits du DataSet.

Synchrone Vs AsynchroneAvec ADO, on peut travailler de manire synchrone ou asynchrone. La programmation asynchrone prsente videmment l'avantage de ne pas bloquer l'application en cas de travaux longs du fournisseur mais demande de grer une programmation vnementielle spcifique. En fait, certains vnements ADO se produiront quels que soient le mode choisi, d'autres ne seront utiliss qu'en mode asynchrone. On peut travailler avec des connexions asynchrones et/ou des commandes asynchrones. Pour travailler de manire asynchrone vous devez utiliser un objet Connection (pas de connexion implicite). Le risque avec le travail asynchrone rside dans la possibilit de faire des erreurs sur des actions dites "bloquantes".

Opration globale (par lot)Les oprations globales sont une suite d'instructions affectant plusieurs enregistrements ou manipulant la structure. Bien que l'on puisse y mettre n'importe quel type d'instructions, on essaye de grouper des oprations connexes dans une opration par lot. Trois types d'oprations globales sont gnralement connus.

Les transactionsLa plupart des SGBDR grent le concept de transaction (on peut le vrifier en allant lire la valeur de Connection.Properties("Transaction DDL")). Une transaction doit toujours respecter les rgles suivantes : v Atomicit : Soit toutes les modifications russissent, soit toutes chouent v Cohrence : La transaction doit respecter l'ensemble des rgles d'intgrit v Isolation : Deux transactions ne peuvent avoir lieu en mme temps sur les mme donnes v Durabilit : Les effets d'une transaction sont dfinitifs. Par contre toute transaction interrompue est globalement annule. Avec ADO, les transactions s'utilisent sur l'objet Connection

Les procdures stockesProcdure crite dans le SGBD qui fait l'opration. Elle prsente de multiples avantages. v Pas de trafic rseau

22

v Environnement scuris v Pas de code complexe pour l'utiliser Par contre, il faut qu'elle soit prvue dans la base ce qui est loin d'tre toujours le cas. Avec ADO elle s'utilise avec l'objet Command.

Gre par le code (traitement par lot)C'est le cas qui nous intresse ici. Vous devez en principe, dans votre code, suivre les mmes contraintes que pour une transaction. Pour ne pas rencontrer trop de problmes je vous conseille d'crire des oprations par lot assez petites. Pour respecter ces rgles vous devez vous assurer par le code que : v La procdure ne dmarre pas si un des enregistrements cible un verrou v Si une erreur ne peut pas tre rsolue pendant le traitement, tout doit tre annul v Si une erreur provient d'une violation d'intgrit, tout doit tre annul v Entre le dmarrage et la fin de la procdure, les enregistrements concerns doivent tre verrouills. C'est rgles ne sont pas inviolables, l'essentiel est de bien vrifier que les modifications ne laissent pas la base dans un tat instable.

Le pige "l'exemple Jet"Nous avons vu que lorsque vous paramtrez votre Recordset vous mettez un souhait de curseur. Rien ne vous dit que ce curseur existe ou est gr par le fournisseur, et qui pluis est, rien ne vous le dira. En effet, le fournisseur cherche vous fournir le curseur demand, s'il ne l'a pas, il vous donnera un curseur s'approchant le plus, mais ne vous enverra jamais de messages d'erreurs. C'est l que le nid bug est dissimul. Selon les fournisseurs, la diffrence entre ce que vous dsirez et ce que vous aurez peut tre norme. Cela explique la plupart des anomalies que vous constatez lors de l'excution de votre code. Nous allons voir tous les problmes que cela peut poser en tudiant le cas des bases Access avec Microsoft Jet 4.0. v Il n'est pas possible d'obtenir un curseur dynamique1 avec JET. v Les curseurs ct serveur sont soit : En lecture seule avec tout type de curseur (sauf dynamique videmment) De type KeySet avec tout type de verrouillage v Les curseurs ct clients sont : Toujours statiques et ne peuvent avoir un verrouillage pessimiste Comme vous le voyez, voil qui rduit fortement le choix de curseurs disponible. Quelles que soient les options choisies, vous aurez un des curseurs donns ci-dessus. Vous aurez par contre toujours un curseur du ct choisi. Evidemment, le problme est quivalent lorsque vous utilisez un contrle de donnes. Ce petit tableau vous donnera le rsum de ce qui est disponible. CursorLocation CursorType LockType ctForwardOnly ctKeyset ltReadOnly ctStatic clUseServer ltReadOnly ltPessimistic ctKeyset ltOptimistic ltBatchOptimistic ctStatic ltReadOnly clUseClient Microsoft affirme que la dclaration d'un curseur dynamique (adDynamic) ct serveur renvoie un curseur KeySet qui aurait de meilleures performances sur les gros Recordset qu'un curseur dclar KeySet. Loin de moi l'ide de mettre en doute une telle affirmation, mais pour ma part je n'ai jamais vu de diffrence notable. 231

ltOptimistic ltBatchOptimistic

Recordset Vs SQLBeaucoup de dveloppeurs expriments prfrent utiliser des requtes actions et du code SQL ds qu'il s'agit de modifier des donnes dans la base (j'entends par modifier, l'ajout, la suppression et la mise jour), plutt que d'utiliser les mthodes correspondantes de l'objet Recordset. Nous avons vu pourquoi cette technique est fortement recommandable si vous matrisez un tant soi peu le SQL, car elle prsente le net avantage de savoir exactement ce qu'on demande au SGBD. Nanmoins si vous ne connaissez pas bien le SQL, cela peut reprsenter plus d'inconvnients que d'avantages. Attention, passer par des requtes Action n'est pas sans risque s'il y a plusieurs utilisateurs car on peut obtenir des violations de verrouillage.

Recordset PersistantAvec ADO il est possible de crer des jeux d'enregistrements persistants. Ceci consiste stocker le jeu d'enregistrement sous la forme d'un fichier. ADO gre deux formats de fichier ADTG et XML. Si le fichier est amen rester sur le poste client je vous conseille d'utiliser le format ADTG (format propritaire), par contre si vous tes amen transfrer ce fichier ou pour des applications Web, utilisez plutt XML. Le fichier se manipule l'aide des mthodes LoadFromFile et SaveToFile.

Optimisation du codeC'est une question qui revient souvent sur les forums. Avant de chercher une quelconque optimisation de votre code ADO, gardez bien l'esprit que la premire chose qui doit tre optimise est votre source de donnes. Les index manquants, les cls mal construites et surtout une structure anarchique de vos tables engendreront une perte de temps qu'aucune optimisation ne sache compenser.

L'optimisation dans l'accs aux donnesCelle ci est propre la programmation des bases de donnes.

Utiliser des requtes compilesSi vous devez excuter plusieurs fois une requte. Celle ci est soit une requte stocke dans la base, soit obtenue en utilisant la proprit "Prepared" de l'objet Command

Utiliser les procdures stockesSi votre SGBD les supporte, utiliser toujours les procdures stockes plutt qu'un code ADO quivalent. En effet, les procdures stockes permettent un accs rapide et scuris au donnes, bien au-del de ce que pourra faire votre code.

Etre restrictif dans les enregistrements / champs renvoysEn effet, on a trop souvent tendance pour simplifier l'criture de la requte rapatrier tous les enregistrements et toutes les colonnes. La plupart du temps, seul certains champs sont utiliss, donc mfiez-vous de l'utilisation du caractre "*". De mme, filtrez l'aide de la clause WHERE quand vous le pouvez.

24

L'objet commandCet objet sert envoyer des requtes SQL (DDL ou DML) vers le SGBD, ainsi qu' la manipulation des procdures stockes. Si cet objet est fondamental dans la programmation d'ADO, c'est srement le moins bien utilis, car le moins bien peru des objets ADO. Cela vient du fait qu'ADO prsente deux aspects trs diffrents l'un de l'autre. Accs une source de donnes "gnrique". Le SGBD cible n'est pas dfini. On ne peut ds lors pas utilis de SQL puisque rare sont les SGBD respectant strictement le standard SQL. C'est un cas de programmation assez rare car il demande une trs bonne connaissance d'ADO pour tre efficace. Dans un tel modle de programmation l'objet Command est peu ou pas utilisable puisque mme la gnration de procdure stocke dans le modle ADOX est gnralement inaccessible. Accs une source de donnes connue. C'est le cas le plus frquent. On utilise ADO pour attaquer un SGBD que l'on connat et dont en gnral on connat le SQL. L'objet Command sert alors de moyen de communication avec le SGBD, gnralement de votre application vers le SGBD, mais aussi dans l'autre sens dans le cas des procdures stockes. Nous verrons que Borland a profit de l'encapsulation pour sparer l'objet en deux ce qui augmente la lisibilit. Mme si vous ne le voyez pas, les jeux d'enregistrements encapsulent leurs propres objets Command que vous pouvez modifier indirectement sans tre oblig de re instancier l'objet.

Communication vers le SGBDL'objet Command doit toujours avoir une connexion valide et ouverte pour pouvoir agir sur la source. On distingue trois cas d'application. Attaque avec commande fige Le texte de la commande est crit en dur soit dans votre application, soit dans le SGBD. C'est de loin le cas le plus simple. Il n'y a pas de paramtres grer. Il est intressant d'utiliser alors des ordres SQL compils (ou prpars). Les procdures stockes sans paramtre et sans renvoi d'enregistrement ainsi que les requtes stockes sans renvoi entrent dans cette catgorie. Attaque avec commande paramtre L'objet Command sert gnralement de fournisseur de paramtre entre le code client et le SGBD. C'est une utilisation standard de l'objet Command. Vous appelez une requte ou une procdure prsente dans la source de donne, l'application cliente donne la valeur des paramtres et la commande est alors excute. Attaque avec commande modulable C'est le concept le plus complexe saisir, assez proche de l'approche ADO.NET du problme. Cela revient mettre dans le code client des requtes gnriques, puis faire appel celle-ci en ne passant que les paramtres. Cette mthode tant trs souple, vous trouverez un exemple dans la troisime partie.

Communication bidirectionnelleElle n'est normalement employe que pour les requtes ou procdures paramtres, stockes dans la source et donnant lieu un renvoi d'information. Nous verrons dans l'tude dtaille de l'objet Command que le retour d'information est diffrent selon qu'il s'agit de paramtre ou d'enregistrement.

Cration de requtes et de procduresL'objet Command est le seul objet prsent dans le modle ADO et dans ADOX. Dans ce dernier, il permet de crer dans la source de donnes des requtes et/ou des procdures, paramtres ou non.

Collection ParametersLes utilisateurs d'autres SGBD qu'Access veilleront bien faire la diffrence entre procdure stocke et requte paramtre.

25

Quoique regroups dans la mme collection, il existe deux types de paramtres. Les paramtres d'entre, attendus par la procdure/requte pour pouvoir s'excuter, et les paramtres de sortie qui peuvent tre renvoys par une procdure. Il convient de faire attention avec ceux-ci, une connexion n'acceptant jamais plus de deux objets Command ayant des paramtres de sortie (le paramtre de retour n'ayant pas d'influence). Les paramtres de cette collection reprsentent les valeurs attendues ou renvoyes par des requtes/procdures stockes dans la source de donnes. Lors de la dfinition d'un paramtre, il faut rigoureusement suivre les rgles suivantes : Utiliser des noms explicites pour vos paramtres. Le paramtre doit toujours tre correctement typ La proprit Size doit toujours tre prcise si le paramtre est de type potentiellement variable (CHAR et VARCHAR) La proprit Direction doit toujours tre prcise

26

TADOConnectionEncapsule l'objet Connection ADO. La liste suivante n'est pas exhaustive.

PropritsAttributes (int)Permet de grer la conservation des annulations ou des validations des transactions de l'objet Connection. Constante Valeur Description Excute un abandon avec sauvegarde : si vous appelez la commande xaAbortRetaining 262144 RollbackTrans, une nouvelle transaction commence automatiquement. Certains fournisseurs ne prennent pas cette valeur en charge. Excute une validation avec sauvegarde : si vous appelez la commande xaCommitRetaining 131072 CommitTrans, une nouvelle transaction commence automatiquement. Certains fournisseurs ne prennent pas cette valeur en charge.

CommandCount (Del), DatasetCount (Del)Permet de connatre le nombre d'objets Command / Dataset attachs une connexion.

Commands(Del), DataSet (Del)Renvoie la collection des objets Command / Dataset actifs de l'objet Connection

CommandTimeout (int)Indique le temps d'attente avant que la commande appele par la mthode Execute ne dclenche une erreur rcuprable. Ne confondez pas cette proprit de l'objet Connection avec celle du mme nom de l'objet Command. Les objets Command attachs une connexion ne tiennent pas compte de la valeur de cette proprit.

Connected (Del)Indique si la connexion est ouverte ou ferme.

ConnectionObject (Del)Permet d'accder directement l'objet Connection intrinsque ADO encapsul dans le composant TADOConnection. L'exemple suivant va vous montrer la technique d'utilisation. begin with ADOConnection1 do begin Provider:= 'Microsoft.Jet.OLEDB.4.0;'; DefaultDatabase:='D:\User\jmarc\tutorial\ADOX\baseheb.mdb'; ConnectionObject.Properties['Jet OLEDB:System database'].Value:='D:\User\jmarc\tutorial\ADOX\system.mdw'; ConnectOptions := coAsyncConnect; Open('Admin','password'); end; end; Dans cet exemple je vais dfinir la vole le fichier de scurit utilis par Access. Pour cela je vais faire appel une proprit dynamique de l'objet Connection "'Jet OLEDB:System database".

27

Toutes les proprits dynamiques ne sont pas encapsules dans Delphi. Pour pouvoir les utiliser, je vais donc devoir atteindre l'objet Connection ADO Intrinsque.

ConnectionString (int)Cette proprit permet de passer une chane contenant tous les paramtres ncessaires l'ouverture de la connexion plutt que de valoriser les proprits une une. C'est cette proprit que l'on utilise avec le composant visuel TADOConnection, mais je vous dconseille de l'utiliser dans le code pour des raisons videntes de lisibilit.

ConnectionTimeout (int)Tel que son nom l'indique. Attention, si CommandTimeout lve une exception, il n'en est pas de mme systmatiquement avec cette proprit. Selon les fournisseurs, il faut parfois aller tester la proprit Connected. De mme, si le fournisseur vous dconnecte pendant l'excution du code, vous ne rcuprerez pas d'erreurs tant que vous n'essayerez pas d'utiliser la connexion.

ConnectOptions (Del)Remplace le paramtre option de la mthode Open ADO. Valeur Constante Description Ouvre la connexion en mode asynchrone. L'vnement coAsyncConnect 16 ConnectComplete peut tre utilis pour dterminer quand la connexion est disponible. coConnectUnspecified -1 (par dfaut) Ouvre une connexion en mode synchrone.* Je vous rappelle qu'en mode non spcifi, le fournisseur peut vous donner une connexion asynchrone.

CursorLocation (int)Permet de dfinir la position du curseur des objets crs partir de cette connexion. Par dfaut il s'agit du cot client.

Errors (int)Renvoie la collection des erreurs de la connexion. Voir l'exemple "Traitement par lot"

IsolationLevel (int)Dfinit le degr d'isolation des transactions. Constante Valeur Description Le serveur utilise un niveau d'isolation diffrent de celui demand et ilUnspecified -1 qui n'a pu tre dtermin.. Valeur utilise par dfaut. Vous ne pouvez pas craser les ilChaos 16 changements en attente des transactions dont le niveau d'isolation est suprieur. IlBrowse ou partir d'une transaction, vous pouvez voir les modifications des 256 ilReadUncommitted autres transactions non encore engages. IlCursorStability ou A partir d'une transaction, vous pouvez afficher les modifications 4096 ilReadCommitted d'autres transactions uniquement lorsqu'elles ont t engages. partir d'une transaction, vous ne pouvez pas voir les modifications ilRepeatableRead 65536 effectues dans d'autres transactions, mais cette nouvelle requte peut renvoyer de nouveaux jeux d'enregistrements. IlSerializable ou 1048576Des transactions sont conduites en isolation d'autres transactions. ilIsolated

28

KeepConnection (Del)Voil une proprit dont il convient de se mfier. Dans le principe, toute connexion n'tant pas lie un Dataset actif se ferme automatiquement. En mettant Vrai cette proprit, on demande le maintien ouvert de la connexion. C'est assez dangereux car : On a facilement tendance oublier de fermer la connexion Le serveur peut dcider malgr tout de la fermer. Il est souvent donc plus rentable cot client de laisser la connexion se fermer puis de la rouvrir pour envoyer les modifications.

Mode (int)Prcise les autorisations de modification de donnes de la connexion. Constante Valeur Description Valeur utilise par dfaut. Indique que les autorisations n'ont pas encore cmUnknown 0 t dfinies ou ne peuvent pas tre dtermines. cmRead 1 Lecture seule. cmWrite 2 Ecriture seule. cmReadWrite 3 Lecture Ecriture. cmShareDenyRead 4 Ouverture interdite pour les utilisateurs autoriss en lecture seule. cmShareDenyWrite 8 Ouverture interdite pour les utilisateurs autoriss en criture seule. cmShareExclusive 12 Ouverture interdite aux autres utilisateurs. Empche les autres utilisateurs d'ouvrir des connexions avec n'importe cmShareDenyNone 16 quelle permission. L'utilisation de cette proprit est loin d'tre triviale comme n