OLE-DB, Visual basic
et Client access Express
OLEDB est probablement le successeur de la norme ODBC
- ODBC est souvent jugé trop lourd
- ODBC ne s'applique qu'aux bases de données
- ODBC n'est pas orienté objet.
Pour toutes ces raisons, Microsoft propose une norme OLEDB, permettant :
- Un accès plus "fin" aux données
- Un accès universel, les données retournées étant
structurées de manière tabulaire.
- On ne parle plus de données à longueur fixe
- encore moins de table
- on retourne un ensemble de lignes (un caractère signal la fin
de ligne)
chaque données dans une ligne étant séparée
par un tabulation.
- On peut donc envisager de travailler avec des données NON database
(des annuaires [LDAP, NDS et ACTIVEX Directory] par exemple)
- et enfin en utilisant un concept OBJET qui est OLE.
Nous avons donc :

(en effet le SDK OLEDB n'est utilisable qu'avec un compilateur C)
Pour rendre l'accès à ces objets plus universel Microsoft les
a encapsulés dans des objets ACTIVEX,
ActiveX Data Object ou ADO :

vous utilisez directement les services rendus par le provider OLEDB qui lui
est en relation avec vos données
(celui d'IBM fournit avec Client access express et la V3R2M0 de Client Access
P. Windows se nomme IBMDA400)
pour terminer se tableau général, si vous n'avez pas de provider
OLEDB (les standards sont SQL server et ORACLE en plus de celui du 400), Microsoft
vous propose un provider OLEDB qui lui même s'appuie sur ODBC: MSDASQL.
.
Prenons un exemple simple et regardons le code associé :
voilà : il s'agit de faire la liste des cours d'un module donné.

C'est un exemple Visual basic.
Il faut déclarer les objets ADO

- Une connexion est un objet permettant de d'établir le lien avec l'AS/400
- un objet command contient un ordre à envoyer à l'AS/400
(requête SQL, commande système, appel à une procédure
cataloguée)
- un objet RecordSet est l'équivalent VB d'un CURSOR SQL, autrement
dit il contient les enregistrements résultat.
Regardons le code , tout d'abord la phase de connexion (lors du chargement
de la fenêtre)
Private Sub Form_Load()
AS400.ConnectionString = "Provider=IBMDA400;Data Source=S44R7480;"
AS400.Open
End Sub |
il faut indiquer :
- un provider (vous retrouvez IBMDA400)
- un nom de système (dans le cas d'un AS/400)
- vous pouvez placer profil et mot de passe (inutile avec Express)
Puis le code de chargement de la liste lors de l'utilisation du bouton "command1"
Private Sub Command1_Click()
Set req = New ADODB.Command
With req
Set .ActiveConnection = AS400 (1)
.CommandType = adCmdText (2)
End With
List1.Clear
Form1.Refresh
req.CommandText = "select * from formationx.cours where af4MDL ='" + Text1.Text
+ "'" (4a)
Set cursor = req.Execute (4b)
cursor.MoveFirst (5)
Do Until cursor.EOF
List1.AddItem (6)(cursor.Fields("AF4MBR")
+ " - " + cursor.Fields("AF4TXT")) (7)
cursor.MoveNext(5)
Loop
End Sub
|
il faut utiliser
- la méthode ActiveConnection de l'objet req (instance de ADODB.command)
pour faire référence à un connexion valide
- la méthode CommandType (du même objet) afin d'indiquer le type
d'ordre à envoyer à l'AS/400
(nous verrons cela plus bas)
- après avoir mis la liste à blanc
- il faut renseigner la requête (4A) puis l'exécuter en plaçant
le résultat dans le RecordSet ( 4b)
- reste à lire séquentiellement le RecordSet
- et à placer chaque ligne dans la liste via AddItem
[vous remarquerez la méthode .FIELDS qui permet d'aller
extraire de la ligne courante une zone d'après son nom (7)]
Principaux Objets d'ADO
Avec pour chaque objet :
- la/les Propriété(s) (paramètre de l'objet à
renseigner par le programme par objet.proriété = valeur)
- la/les méthode(s) (actions liée à l'objet que votre
programme peut lancer sous la forme objet.méthode)
Connection
|
(private cn as new ADODB.connection) |
connectionstring (Propriété) |
identifie le OLEDB Provider
cn.connectionstring = "Provider=IBMDA400;Data Source=S44xxxx"
|
Open (Méthode) |
établit la connexion avec le serveur |
Close (Méthode) |
coupe la connexion |
Execute (Méthode) |
execute une commande sur le serveur
set resultat = cn.execute "Select * from fichier"
(il est préférable d'utiliser un objet commande)
|
BeginTrans
CommitTrans
RollbackTrans
|
Utilisé pour démarrer une transaction puis pour valider
ou annuler une transaction si vous travaillez sous contrôle de validation.
|
Command
|
(private cmd as new ADODB.Command) |
activeconnection (Propriété) |
Fait référence à une connexion établie
set cmd.activeconnection = cn
|
Commandtext |
chaîne représentant la commande à exécuter
ou le fichier à ouvrir
pour les fichiers à ouvrir ou les ordres SQL , "chaîne"
pour les procédures cataloguées, "{chaîne}"
pour les programmes à appeller et les commandes, "{{chaîne}}"
Pour les data queues, "OPEN DATAQUEUE .... FOR SEND"
cmdFichier.CommandText = "biblio.fichier(*FIRST)"
cmdIFS.CommandText = "/QSYS.LIB/biblio.lib/fichier.file/%FIRST%.mbr"
cmdSQL.CommandText = "Select * From ... Where ..."
cmdProcedurecataloguée="{CALL BIB.PROC (?,?,?)}"
cmdProgramme="{{CALL /QSYS.LIB/BIBLIO.LIB/MONPROG.PGM(?,?,?,?)}}"
cmdDTAQ=" OPEN DATAQUEUE /QSYS.LIB/BIBLIO.LIB.MADTAQ.DTAQ(data
char(xxx))) FOR SEND"
cmdCommande="{{QSYS/CRTLIB LIB(essai)}}"
|
CommandType |
indique le type de commande à executer
pour IBMDA400,
adCmdTable pour une ouverture de fichier
adCmdText pour toutes les autres commandes
(ne pas utiliser adCmdStoredProc)
|
Prepared |
indique si la commande doit être "préparée"
c'est à dire interprétée puis sauvegardée
pour utilisation répétée.(au moins trois ou quatre
fois pour que l'opération soit rentable)
cmd.Prepared = True | False
|
Createparameter |
Sert à définir un paramètre devant être utilisé
lors d'un appel à une procédure cataloguée ou à
un programme (Voir la collection Parameters) |
Execute
|
Exécute l'ordre associé à l'objet commande (CommandText
doit être renseigné)
set recordset = cmd.execute (pour un retour d'enregistrement [Select,
procédure, Dtaq].)
cmd.execute (pour une commande sans retour [Insert, Update SQL].)
|
RecordSet
|
(private rs as new ADODB.RecordSet) |
activeconnection (Propriété) |
Fait référence à une connexion établie
set rs.activeconnection = cn
|
BOF /EOF
(propriété) |
Signale le début (BOF) ou la fin (EOF) de fichier dans le recordset
si le recordSet est vide les deux propriétés sont
vraies
si le RecordSet est non vide à l'ouverture les deux propriétés
sont fausses et vous êtes positionné sur la première
ligne.
l'utilisation courante est la suivante :
If (not rs.EOF) and (not rs.bof) Then
do until rs.EOF
.... (traitement) ...
rs.MoveNext
loop
Endif
|
BookMark
(propriété) |
Permet de mémoriser un positionnement
Mémorisation : pos = rs.BookMark
retour à la ligne dont on a mémorisé la position
: rs.BookMark = pos
|
EditMode |
Retourne une information indiquant si la ligne a été modifiée
adEditNone : la ligne en cours est non modifiée
adEditinProgress : les données de la ligne en cours ont
étées modifiées, les modifs ne sont pas répercutées
dans le RecordSet et donc dans la base, jusqu'à rs.UPDATE.
adEditAdd : des données ont étées ajoutées
(dans le buffer, voir AddNew), les modifs ne sont pas répercutées,
jusqu'à rs.UPDATE.
|
AddNew
(Méthode)
|
Définit un buffer pour stockage des données à ajouter.
rs.Addnew
rs("ZONE1") = valeur1
rs("ZONE2") = valeur2
rs.Update
|
Open |
Alternative à la méthode execute [rs.open = cmd] |
Close |
Ferme un Recorset |
Requery |
rafraichit les données du RecordSet |
Supports |
Indique si une méthode est supportée par le provider OLEDB
if rs.Supports(adAddNew) then ...
|
Update
|
rend actives les mises à jour et les ajouts en instance dans le
recordSet
(et donc met à jour la base de données)
|
Les objets que nous allons voir ici sont en fait des tableaux d'objets , ou
des Collections .
Fieds liste des champs d'une table
Errors listes des erreurs recues
Parameters liste des paramètres associés à
un objet Command.
Fields
|
déclarée automatiquement avec le RecordSet
pour indiquer un Champ dans la collection on indice par :
- soit un chiffre rs.fields(0) représente le premier champ
- soit un nom de champ rs.fields("NOCLI") représente
la zone NOCLI
|
ActualSize
(propriété)
|
Indique (pour le champ référencé) la taille actuelle
en nbr de caractère ou -1 pour le numérique
|
Attributes
(propriété) |
Indique
- AdFldUpdatable (valeur 4) que le champ est modifiable
- AdFldFixed (valeur 16) que le champ n'est pas à lg variable
la valeur retournée peut être 20 (4 + 16)
|
DefinedSize
(propriété) |
Indique (pour le champ référencé) la taille définie
dans la base ou -1 pour le numérique
|
Name
(propriété) |
Retourne le nom du champ
|
Precision
(propriété)
|
Retourne (pour un champ numérique) le nombre d'entiers
|
NumericScale
(propriété) |
Retourne (pour un champ numérique) le nombre de décimales |
Type |
Retourne le type de champ :
DBTYPE_I2 |
Binaire 2 octets |
DBTYPE_I4 |
Binaire 4 octets |
DBTYPE_R4 |
virg. flottante simple précision |
DBTYPE_R8 |
virg. flottante double précision |
DBTYPE_BYTE |
type Hexa ou Char avec CCSID 65535 |
DBTYPE_DECIMAL |
numérique packé |
DBTYPE_NUMERIC |
numérique étendu |
DBTYPE_STR |
tout le reste : CHAR,DATE,TIME |
|
OriginalValue |
valeur dans le RecordSet (intacte jusqu'à UPDATE) |
Value |
Valeur en cours (c'est la propriété par défaut)
|
Errors
|
déclarée automatiquement avec l'objet Connection
Utilisation courrante :
if cn.Errors.Count > 0 then
for each ADOError in cn.Errors
msg = msg + " N°=" + ADOError.number +
" Texte=" + ADOError.Description + vbcrlf
next
Msgbox msg, VbOKOnly, "Erreurs rencontrées"
EndIf
|
Number |
N° du message |
Description
(propriété)
|
Texte du message, il commence par l'ID message au sens 400
- CWBZZxxxx : Message du provider OLEDB
- CWBDBxxxx : Message base de données
- CPFxxxx : Message OS/400
- SQLxxxx : Message SQL/400
|
Source |
Origine du message
- "IBMDA400 Session" dans le cas du provider de Client
Access
|
Parameters
|
Dim P1 as New ADODB.Parameter
Utilisation courrante :
Dim cmd as new ADODB.Command
Dim P1 as new ADODB.Parameter
Dim P2 as new ADODB.Parameter
With cmd
Set .ActiveConnection = AS400
.CommandType = adCmdText
.CommandText = "{CALL BIB/PROC (?,?)}"
.prepared = true
End With
Set P1 = cmd.CreateParameter(Name:="P1", Type:=adChar,
Direction:=adParamInput,
Size:=7,
Value:="NANTES ")
Set P2 = cmd.CreateParameter(Name:="P2", Type:=adInteger,
Direction:=adParamInputOutput,
Size:=3,
Value:=987)
cmd.Parameters.Append P1
cmd.Parameters.Append P2
cmd.Execute
retour = cmd.Parameters("P2")
|
Direction |
Utilisation du paramètre
- adparamInput (paramètre envoyé à la procédure)
- adparamOutput (paramètre recu de la procédure)
- adparamInputOutput (paramètre envoyé à la procédure
et recuen retour)
- adparamReturnValue (le paramètre est une valeur retournée
par la procédure [fontion].)
|
name |
nom du paramètre
|
NumericScale |
Nbr de décimales du paramètre
|
Precision |
NBr d'entiers du paramètre |
Size |
Taille (nbr d'octets ) du paramètre |
Type |
type de paramètre (un des types ADO valides) :
DBTYPE_EMPTY |
vide (sans valeur) |
DBTYPE_NULL |
valeur nulle |
DBTYPE_RESERVED |
réservé (pour usage ultérieur) |
DBTYPE_I1 |
Binaire (1 octet) |
DBTYPE_I2 |
Binaire (2 octets) |
DBTYPE_I4 |
Binaire (4 octets) |
DBTYPE_I8 |
Binaire (8 octets) |
DBTYPE_UI1 |
binaire non signé (1octet) |
DBTYPE_UI2 |
binaire non signé (2octets) |
DBTYPE_UI4 |
binaire non signé (4octets) |
DBTYPE_UI8 |
binaire non signé (8octets) |
DBTYPE_R4 |
virg. flottante simple précision |
DBTYPE_R8 |
virg. flottante double précision |
DBTYPE_CY |
valeur monétaire (currency) |
DBTYPE_DECIMAL |
numérique packé |
DBTYPE_NUMERIC |
numérique étendu |
DBTYPE_DATE |
Date OLE |
DBTYPE_BOOL |
Booléen |
DBTYPE_BYTES |
variable au contenu binaire |
DBTYPE_UDT |
structure définie par l'utilisateur
|
DBTYPE_STR |
Chaîne Ansi terminée par x'00' |
DBTYPE_WSTR |
Chaîne UNICODE |
DBTYPE_VARIANT |
Variant OLE |
DBTYPE_ERROR |
code erreur sur 32 bits |
DBTYPE_BYREF |
pointeur vers une variable |
DBTYPE_DBDATE |
Structure de type DATE |
DBTYPE_DBTIME |
Structure de type TIME |
DBTYPE_DBTIMESTAMP |
Structure de type TIMESTAMP |
|
Value |
Valeur du paramètre |
Pour terminer voici deux exemples en VB :
1/ utilisation d'une procédure cataloguée pour vérifier
les droits sur un fichier
ci dessous le source du pgm (c'est un CL)
************** Début des données ************************
PGM
PARM(&FICHIER &BIB &AUT)
DCL &FICHIER *CHAR 10
DCL &BIB *CHAR 10
DCL &AUT *CHAR 1
CHGVAR VAR(&AUT) VALUE('O')
CHKOBJ OBJ(&BIB/&FICHIER) OBJTYPE(*FILE) AUT(*USE)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&AUT) VALUE('N'))
ENDPGM
*************** Fin des données **************************
|
cette procédure sera enregistrée par :
CREATE PROCEDURE FORMATIONX/PROCCHKAUT
(IN FICHIER CHAR (10 ),
IN BIB CHAR (10 ),
OUT AUT CHAR (1 ))
LANGUAGE CL NOT DETERMINISTIC CONTAINS SQL EXTERNAL PARAMETER STYLE GENERAL
puis le source VB

--------------déclarations générales---------------
Public AS400 As New ADODB.Connection
Public req As New ADODB.Command
------au chargement de la fenêtre------
Private Sub Form_Load()
AS400.ConnectionString = "Provider=IBMDA400;Data Source=S44R7480;" AS400.Open
End Sub
------sur un click du bouton "lancer"------
Private Sub Command1_Click()
Dim P1 As New ADODB.Parameter
Dim P2 As New ADODB.Parameter
Dim p3 As New ADODB.Parameter
Set req = New ADODB.Command
With req
Set .ActiveConnection = AS400
.CommandType = adCmdText
.CommandText = "{CALL FORMATIONX.PROCCHKAUT
(?,?,?)}"
.Prepared = True
End With
Set P1 = req.CreateParameter(Name:="P1", Type:=adChar, Direction:=adParamInput,
Size:=10, Value:="COURSc") *
Set P2 = req.CreateParameter(Name:="P2", Type:=adChar, Direction:=adParamInput,
Size:=10, Value:="FORMATIONX")
Set p3 = req.CreateParameter(Name:="P3", Type:=adChar, Direction:=adParamOutput,
Size:=1)
req.Parameters.Append P1
req.Parameters.Append P2
req.Parameters.Append p3
req.Execute
MsgBox req.Parameters("P3")
End Sub
|
*
ce fichier
n'existe pas
2/ Utilisation en VB6 d'un objet graphique Data CONTROL - ADO

cet objet graphique possède deux propriétés remarquables
:
- ConnectionString
paramètres de connexion au provider OLEDB
- RecordSource
ordre SQL associé
"Select ..."
ou "{CALL ..}"
|
 |
On peut ensuite associer à cet objet un control "DataGrid"
en renseignant la propriété
DataSource avec le nom du DataControl.

Ce qui nous donne :

le code associé est le suivant :
Private Sub Command1_Click()
Dim requete As String
Dim where
requete = " "
where = " "
requete = "select * from formationx.cours"
If Text1.Text <> " " And Text1.Text <> "" Then
where = "where af4mdl = '" + Text1.Text + "'"
End If
If Text2.Text <> " " And Text2.Text <> "" Then
If where = " " Then
where = "where"
Else
where = where + " AND "
End If
where = where + " sujet = '" + Text2.Text + "'"
End If
If where <> " " Then
requete = requete + " " + where
End If
cours.RecordSource = requete
cours.Refresh
Form1.Refresh
End Sub
|
©AF400