Remerciements▲
Je remercie Thomas Lebrun pour son tutoriel sur Oracle et .NET qui m'a servi de fil conducteur. Je remercie également phara (les habitués de developpez.com savent de qui je parle) pour la relecture de ce tutoriel.
I. Introduction▲
Dans ce tutoriel, nous supposerons que vous possédez déjà des notions d'ADO.NET.
Pour faire interagir une application .NET et DB2, vous pouvez utiliser les trois méthodes classiques :
- via ODBC, la méthode de connexion à une base de données la plus ancienne et la plus répandue, mais aussi la moins performante ;
- via OLEDB, la méthode la plus courante aujourd'hui et qui offre une certaine portabilité ;
- via un provider spécifique conçu exclusivement pour DB2, la méthode théoriquement la plus performante.
Ici, nous explorerons uniquement la troisième méthode. L'utilisation des deux autres méthodes ne différent en rien de leur utilisation avec une autre base de données si ce n'est la chaîne de connexion et des spécificités au niveau du langage SQL de DB2.
Actuellement, il existe deux providers spécifiques pour DB2. L'un produit par IBM et l'autre créé dans le cadre du projet MONO. Dans ce tutoriel, je parlerai essentiellement du provider DB2 développé par IBM toutefois, pratiquement tous les exemples fonctionnent également avec le provider fourni avec MONO.
II. IBM DB2 Data Provider▲
II-A. Le provider DB2 d'IBM▲
Le provider DB2 créé par IBM est disponible (en version bêta) au moins depuis la version 8.1.3. Il fait partie intégrante du projet « Stinger » qui a abouti à la version 8.2 où il est fourni en version de production. Personnellement, j'ai utilisé la version bêta 8.1.2.1. DB2 peut être téléchargé gratuitement en version personnelle ici. Vous pouvez également trouver la documentation complète du provider dotnet ici.
II-B. Le provider DB2 de Mono▲
Si vous utilisez Mono, ce provider fait partie intégrante du package. Aucune installation complémentaire n'est nécessaire. Si vous le désirez, Mono étant fourni sous licence GPL, vous pouvez extraire le provider du code source et le compiler avec le framework de Microsoft. Vous trouverez le projet Mono ici.
III. DB2 et .NET▲
III-A. Ajout des références▲
Avant d'utiliser le provider, vous devez ajouter une référence dans votre projet. Pour cela, que vous utilisiez VS.NET ou SharpDevelop, faites un clic droit sur références, dans votre explorateur de solution, puis choisissez « Ajouter une référence ». Choisissez « Parcourir » et sélectionnez le fichier IBM.Data.DB2.dll que vous trouverez en principe sous le répertoire c:\Program Files\IBM\SQLLIB\BIN\netf11.
Ultérieurement, vous pourrez retrouver directement la référence dans le premier écran sous l'appellation IBM.DATA.DB2.
III-B. Création de la connexion▲
Comme pour tout accès à une DB depuis .NET, la première chose à faire est de créer une connexion à DB2. Pour y parvenir, vous devez utiliser l'objet DB2Connection. Le paramétrage de votre connexion se fait au moyen de la propriété ConnectionString qui est initialisée via le constructeur.
// Création de la connexion.
string
connString =
"Database=Test;UID=myUser;PWD=myPassword"
;
DB2Connection conn =
new
DB2Connection
(
connString);
' Création de la connexion.
Dim
connString As
String
=
"Database=Test;UID=myUser;PWD=myPassword"
Dim
conn As
DB2Connection =
New
DB2Connection
(
connString)
Vous pouvez également séparer l'initialisation de la chaîne de connexion du constructeur.
// Création de la connexion.
DB2Connection conn =
new
DB2Connection
(
);
conn.
ConnectionString =
"Database=Test;UID=myUser;PWD=myPassword"
;
' Création de la connexion.
Dim
conn As
DB2Connection =
New
DB2Connection
(
)
conn.ConnectionString
=
"Database=Test;UID=myUser;PWD=myPassword"
III-C. Ouverture/Fermeture de la connexion▲
Pour ouvrir ou fermer la connexion, il suffit d'utiliser les méthodes Open et Close.
// Ouverture de la connexion.
conn.
Open
(
);
...
// Fermeture de la connexion.
conn.
Close
(
);
// Libération des ressources.
conn.
Dispose
(
);
' Ouverture de la connexion.
conn.Open
...
' Fermeture de la connexion.
conn.Close
' Libération des ressources.
conn.Dispose
Vous pouvez connaitre l'état d'une connexion au moyen de la propriété State. Cette propriété est du type « ConnectionState ».
ConnectionState.Open
ConnectionState.Closed
ConnectionState.Connecting
ConnectionState.Executing
ConnectionState.Fetching
ConnectionState.Broken
III-D. Exécuter une requête SQL▲
Pour exécuter une commande SQL, vous devez utiliser l'objet DB2Command.
// Création de l'objet DB2Command lié à notre connexion.
DB2Command sqlCmd =
conn.
CreateCommand
(
);
// Requête SQL à exécuter.
sqlCmd.
CommandText =
"SELECT nom, prenom FROM monSchema.maTable"
;
// Type de requête. Les valeurs possibles sont Text, StoredProcedure et TableDirect.
sqlCmd.
CommandType =
CommandType.
Text;
' Création de l'objet DB2Command lié à notre connexion.
Dim
sqlCmd As
DB2Command =
conn.CreateCommand
' Requête SQL à exécuter.
sqlCmd.CommandText
=
"SELECT nom, prenom FROM monSchema.maTable"
' Type de requête. Les valeurs possibles sont Text, StoredProcedure et TableDirect.
sqlCmd.CommandType
=
CommandType.Text
Il ne vous reste alors qu'à appeler une des trois méthodes classiques que sont ExecuteNonQuery, ExecuteReader, ExecuteScalar.
III-E. Lecture des enregistrements▲
Pour lire les enregistrements, il suffit d'utiliser un objet DB2DataReader.
// Instanciation du Db2DataReader.
DB2DataReader reader =
sqlCmd.
ExecuteReader
(
);
// Lecture des enregistrements.
while
(
reader.
Read
(
)){
MessageBox.
Show
(
reader.
GetString
(
0
).
Trim
(
) +
" "
+
reader.
GetString
(
1
).
Trim
(
));
}
reader.
Close
(
);
' Instanciation du Db2DataReader.
Dim
reader As
DB2DataReader =
sqlCmd.ExecuteReader
' Lecture des enregistrements.
While
reader.Read
MessageBox.Show
(
reader.GetString
(
0
).Trim
+
" "
+
reader.GetString
(
1
).Trim
)
End
While
reader.Close
III-F. Contrôler l'exécution avec une transaction▲
Pour gérer les transactions, vous disposez de l'objet DB2Transaction. Dans son utilisation la plus simple et la plus courante, on instanciera la transaction au moyen de la méthode BeginTransaction de l'objet DB2Connection. La transaction sera terminée au moyen de la méthode Commit ou de la méthode RollBack si celle-ci ne doit finalement pas être réalisée.
// Initialisation de la transaction depuis la connexion.
DB2Transaction trans =
conn.
BeginTransaction
(
);
// Création et exécution de la/des commandes à exécuter.
DB2Command sqlCmd =
conn.
CreateCommand
(
);
// La commande est placée sous contrôle de la transaction.
sqlCmd.
Transaction =
trans;
sqlCmd.
CommandType =
CommandType.
Text;
sqlCmd.
CommandText =
"INSERT INTO db2admin.Test2 (nom, prenom) VALUES ('A','A')"
;
try
{
if
(
sqlCmd.
ExecuteNonQuery
(
)!=
0
)
{
// La transaction peut être confirmée.
trans.
Commit
(
);
}
else
{
// Les opérations effectuées doivent être annulées.
trans.
Rollback
(
);
MessageBox.
Show
(
"Erreur d'écriture dans la base de données"
);
}
}
catch
(
Exception ex)
{
// Les opérations effectuées doivent être annulées.
trans.
Rollback
(
);
MessageBox.
Show
(
"Erreur d'écriture dans la base de données: "
+
ex.
Message);
}
sqlCmd.
Dispose
(
);
' Initialisation de la transaction depuis la connexion.
Dim
trans As
DB2Transaction =
conn.BeginTransaction
' Création et exécution de la/des commandes à exécuter.
Dim
sqlCmd As
DB2Command =
conn.CreateCommand
' La commande est placée sous contrôle de la transaction.
sqlCmd.Transaction
=
trans
sqlCmd.CommandType
=
CommandType.Text
sqlCmd.CommandText
=
"INSERT INTO db2admin.Test2 (nom, prenom) VALUES ('A','A')"
Try
If
Not
(
sqlCmd.ExecuteNonQuery
=
0
) Then
' La transaction peut être confirmée.
trans.Commit
Else
' Les opérations effectuées doivent être annulées.
trans.Rollback
MessageBox.Show
(
"Erreur d'écriture dans la base de données"
)
End
If
Catch
ex As
Exception
' Les opérations effectuées doivent être annulées.
trans.Rollback
MessageBox.Show
(
"Erreur d'écriture dans la base de données: "
+
ex.Message
)
End
Try
sqlCmd.Dispose
III-G. Les requêtes paramétrées▲
Il est bien évidemment possible de réaliser des requêtes paramétrées. Ce type de requêtes permet d'améliorer les performances, mais aussi d'éviter des problèmes de conversion de données lors de la concaténation de votre chaîne SQL. Vous pouvez constater dans le code ci-dessous qu'une date reste une date. Elles sont également nécessaires pour des raisons de sécurité dans la lutte contre l'injection de code SQL.
// Création de la commande.
Db2Command cmdSql =
conn.
CreateCommand
(
);
cmdSql.
CommandType =
CommandType.
Text;
cmdSql.
CommandText =
"SELECT nom, prenom FROM monSchema.maTable WHERE date>? AND pays=?"
;
// Ajout des paramètres.
cmdSql.
Parameters.
Add
(
"Date"
,
DB2Type.
Date);
cmdSql.
Parameters.
Add
(
"Pays"
,
DB2Type.
Char,
2
);
// Préparation de la commande sur le serveur.
cmdSql.
Prepare
(
);
// Passage des paramètres.
cmdSql.
Parameters[
0
].
Value =
DateTime.
Now;
cmdSql.
Parameters[
1
].
Value =
"BE"
;
// Exécution de la commande.
Db2DataReader reader =
cmdSql.
ExecuteReader
(
);
' Création de la commande.
Dim
cmdSql As
Db2Command =
conn.CreateCommand
cmdSql.CommandType
=
CommandType.Text
cmdSql.CommandText
=
"SELECT nom, prenom FROM monSchema.maTable WHERE date>? AND pays=?"
' Ajout des paramètres.
cmdSql.Parameters.Add
(
"Date"
, DB2Type.Char
)
cmdSql.Parameters.Add
(
"Pays"
, DB2Type.Char
, 128
)
' Préparation de la commande sur le serveur.
cmdSql.Prepare
' Passage des paramètres.
cmdSql.Parameters
(
0
).Value
=
DateTime.Now
cmdSql.Parameters
(
1
).Value
=
"BE"
' Exécution de la commande.
Dim
reader As
Db2DataReader =
cmdSql.ExecuteReader
III-H. Remplir un DataSet▲
Pour remplir un DataSet, il suffit d'utiliser l'objet DB2DataAdapter exactement comme pour le provider OleDb.
// Création de la commande.
DB2Command cmdSql =
new
DB2Command
(
);
cmdSql.
Connection =
conn;
cmdSql.
CommandText =
"SELECT * FROM db2admin.Test2"
;
// Création du DataAdapter.
DB2DataAdapter da =
new
DB2DataAdapter
(
);
da.
SelectCommand =
cmdSql;
// Création du DataSet.
DataSet ds =
new
DataSet
(
);
// On rempli le DataSet et on ferme le DataAdapter.
da.
Fill
(
ds,
"Test2"
);
da.
Dispose
(
);
cmdSql.
Dispose
(
);
' Création de la commande.
Dim
cmdSql As
DB2Command =
New
DB2Command
cmdSql.Connection
=
conn
cmdSql.CommandText
=
"SELECT * FROM db2admin.Test2"
' Création du DataAdapter.
Dim
da As
DB2DataAdapter =
New
DB2DataAdapter
da.SelectCommand
=
cmdSql
' Création du DataSet.
Dim
ds As
DataSet =
New
DataSet
' On remplit le DataSet et on ferme le DataAdapter.
da.Fill
(
ds, "Test2"
)
da.Dispose
cmdSql.Dispose
III-I. Récupérer la structure d'une table▲
Il est très simple de récupérer la structure d'une table, pour cela, nous utilisons simplement la méthode GetSchemaTable. Dans l'exemple, nous afficherons uniquement les noms des champs. À vous de compléter pour obtenir les autres renseignements.
// Création de la commande.
DB2Command sqlCmd =
conn.
CreateCommand
(
);
sqlCmd.
CommandType =
CommandType.
TableDirect;
sqlCmd.
CommandText =
"monSchema.maTable"
;
// Lecture de la structure dans le DataReader.
DB2DataReader reader =
sqlCmd.
ExecuteReader
(
CommandBehavior.
SchemaOnly);
// Exportation du schéma vers une DataTable.
DataTable schemaTable =
reader.
GetSchemaTable
(
);
// Lecture du schéma.
Table tbl =
(
Table)tables[
"monSchema.maTable"
];
foreach
(
DataRow row in
schemaTable.
Rows)
{
MessageBox.
Show
(
"Nom: "
+
(
string
)row[
"ColumnName"
]
);
}
reader.
Close
(
);
' Création de la commande.
Dim
sqlCmd As
DB2Command =
conn.CreateCommand
sqlCmd.CommandType
=
CommandType.TableDirect
sqlCmd.CommandText
=
"monSchema.maTable"
' Lecture de la structure dans le DataReader.
Dim
reader As
DB2DataReader =
sqlCmd.ExecuteReader
(
CommandBehavior.SchemaOnly
)
' Exportation du schéma vers une DataTable.
Dim
schemaTable As
DataTable =
reader.GetSchemaTable
' Lecture du schéma.
Dim
tbl As
Table =
CType
(
tables
(
"monSchema.maTable"
), Table)
For
Each
row As
DataRow In
schemaTable.Rows
MessageBox.Show
(
"Nom: "
+
CType
(
row
(
"ColumnName"
), String
))
Next
reader.Close
IV. Add-in pour Visual Studio▲
En plus du provider, IBM fournit un Add-in pour Visual Studio. Ce tutoriel n'ayant pas pour but de vous présenter cet Add-in, je vous laisse le découvrir ici.
V. Conclusions▲
Comme vous le voyez, travailler avec le provider spécifique de DB2 ne présente aucune difficulté particulière. Que vous soyez habitués à travailler avec OleDB, SqlServer ou un autre provider, le passage vers le provider DB2 se fera sans heurt. Ce tutoriel est loin de présenter toutes les fonctionnalités offertes, il ne vous reste plus qu'à découvrir le reste.
Il est par ailleurs regrettable qu'IBM ne mette pas plus avant ces possibilités. Je n'ai par exemple pas pu trouver la possibilité de télécharger le provider sans la version complète de DB2. Impossible également de trouver les mises à jour du provider. J'ai tenté également d'obtenir un complément d'information auprès d'eux, mais sans succès.