OLE-DB, Visual basic
et Client access Express






OLEDB est probablement le successeur de la norme ODBC

  1. ODBC est souvent jugé trop lourd
  2. ODBC ne s'applique qu'aux bases de données
  3. ODBC n'est pas orienté objet.

Pour toutes ces raisons, Microsoft propose une norme OLEDB, permettant :

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

 

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 :

  1. un provider (vous retrouvez IBMDA400)
  2. un nom de système (dans le cas d'un AS/400)
  3. 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

  1. la méthode ActiveConnection de l'objet req (instance de ADODB.command) pour faire référence à un connexion valide
  2. la méthode CommandType (du même objet) afin d'indiquer le type d'ordre à envoyer à l'AS/400
    (nous verrons cela plus bas)
  3. après avoir mis la liste à blanc
  4. il faut renseigner la requête (4A) puis l'exécuter en plaçant le résultat dans le RecordSet ( 4b)
  5. reste à lire séquentiellement le RecordSet
  6. 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 :

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