Utilisation de DB2 en .NET

Jean-Alain Baeyens

Le produit DB2 d'IBM est un gestionnaire de base de données multiplateforme ayant déjà une longue histoire. Il reste un acteur important dans le domaine des bases de données. Voyons comment y accéder en .NET. ♪

- Titre : Utilisation de DB2 en .NET

- Auteur : Jean-Alain Baeyens

- Parution : 16 mars 2005

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2020 Jean-Alain Baeyens. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Remerciements

- I. Introduction

- II. IBM DB2 Data Provider

- II-A. Le provider DB2 d'IBM

- II-B. Le provider DB2 de Mono

- III. DB2 et .NET

- III-A. Ajout des références

- III-B. Création de la connexion

- III-C. Ouverture/Fermeture de la connexion

- III-D. Exécuter une requête SQL

- III-E. Lecture des enregistrements

- III-F. Contrôler l'exécution avec une transaction

- III-G. Les requêtes paramétrées

- III-H. Remplir un DataSet

- III-I. Récupérer la structure d'une table

- IV. Add-in pour Visual Studio

- V. Conclusions

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.

C#

// Création de la connexion.
string connString = "Database=Test;UID=myUser;PWD=myPassword";
DB2Connection conn = new DB2Connection(connString);

VB.NET

' 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.

C#

// Création de la connexion.
DB2Connection conn = new DB2Connection();
conn.ConnectionString = "Database=Test;UID=myUser;PWD=myPassword";

VB.NET

' 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.

C#

// Ouverture de la connexion.
conn.Open();
...
// Fermeture de la connexion.
conn.Close();
// Libération des ressources.
conn.Dispose();

VB.NET

' 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 ».

Valeurs possibles:

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.

C#

// 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;

VB.NET

' 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.

C#

// 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();

VB.NET

' 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.

C#

// 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();

VB.NET

' 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.

C#

// 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();

VB.NET

' 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.

C#

// 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();

VB.NET

' 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.

C#

// 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();

VB.NET

' 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.