Sébastien Pertus
Créer une classe d'accès aux données avec ADO.Net 2.0
Accès générique Ado.Net 2.0
Par Sébastien Pertus publié le 14/05/2006 à 22:34, lu 9298 fois, 7 pages
 4 | Concept de fabrique de classe
Téléchargez le code source - 60 Kb
Concept de fabrique de classe
Voici une des nouvelles classes issus de System.Data.Common et suremment l'une des plus importantes : DbProviderFactory.
Cette classe permet de créer tous les objets nécessaires (Command, Connection ...) à la construction de notre classe d'accés aux données. DbProviderFactory permet d'implémenter des Providers d'accés aux données qui implémentent certaines règles. Il existe déjà plusieurs Providers, et vous pouvez si vous le souhaitez créer le votre (pour peu que celui ci n'existe pas déjà)

Où se trouve la défintion de ces providers existants ?
Dans le machine.config :
Voici ce que contient notamment votre machine.config (localisé sur C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG) au sujet des providers :
  <system.data>
    <DbProviderFactories>
      <add name="Odbc Data Provider" 
           invariant="System.Data.Odbc" 
           description=".Net Framework Data Provider for Odbc" 
           type="System.Data.Odbc.OdbcFactory, System.Data, 
             Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <add name="OleDb Data Provider" 
           invariant="System.Data.OleDb" 
           description=".Net Framework Data Provider for OleDb" 
           type="System.Data.OleDb.OleDbFactory, System.Data, 
             Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <add name="OracleClient Data Provider" 
           invariant="System.Data.OracleClient" 
           description=".Net Framework Data Provider for Oracle" 
           type="System.Data.OracleClient.OracleClientFactory, System.Data.OracleClient, 
             Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <add name="SqlClient Data Provider" 
           invariant="System.Data.SqlClient" 
           description=".Net Framework Data Provider for SqlServer" 
           type="System.Data.SqlClient.SqlClientFactory, System.Data, 
             Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </DbProviderFactories>
  </system.data>
Comment utiliser ces fabriques fournies par le framework .net ?

Notre objet DbProviderFactory utilise ces définitions pour créer par réflection la bonne fabrique de classe.
En utilsant notre classe DbProviderFactory on pourrait écrire :
DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory(System.Data.SqlClient);
Vous venez d'implémenter la fabrique des classes de System.Data.SqlClient
Ces définitions se retrouvent aussi dans vos fichiers de configurations, notamment dans la partie dédiée aux chaines de connexion.
Voici un exemple d'un fichier de configuration web.config :
<connectionStrings>
    <add name="ConnectionStringName" 
    connectionString="Data Source=MonServeur;Initial Catalog=bd;User ID=sa"
    providerName="System.Data.SqlClient"/>
</connectionStrings>

Notrez le nouveau tag <connectionStrings> directement intégré dans le fichier de configuration ; là où il fallait le créer manuellement avec Ado 1.x dans une section <appSettings> par exemple.

Nous avons besoin de récupérer le Provider utilisé dans notre fichier de configuration, pour renvoyer les instances des objets correct et correspondant au provider sélectionné.

Nous allons utiliser la classe ConfigurationManager, issue de System.Configuration.
Cette classe permet notamment de récupérer facilement les chaines de connexion de votre fichier de configuration.

Une fois le provider récupéré, il ne reste plus qu'à créer notre fabrique d'objets.

Où implémenter ce morceau de code ?

Il suffit de se poser la bonne question : Quand est ce le plus utile ? Et bien au début, à l'initialisation, à la création de notre instance !
Le constructeur semble alors l'endroit tout indiqué pour cette opération :
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Configuration;
using System.Data;
using System.Collections;
using System.Reflection;
using System.Transactions;

namespace GenericAccess
{
    public class Data
    {
        #region Proprits Prives
        private ConnectionStringSettings connectionStringSettings;
        private ConnectionStringSettingsCollection connectionStringsCollection;
        #endregion

        #region Pattern Singleton
        private static Data instance;
        static Data()
        {
            instance = new Data();

            // Rcupration de toutes les chaines de connexion
            instance.connectionStringsCollection = ConfigurationManager.ConnectionStrings;

         }
        public static Data GetInstance()
        {
            return instance;
        }
        #endregion
    }
}

A quoi sert une classe issue de DbProviderFactory ?

Cette classe va créer pour nous, tous les objets nécessaires, quelque soit le provider paramétré dans votre fichier de configuration.
Voici un aperçu des nombreuses fonctions, que nous allons utiliser, contenues dans DbProviderFactory :
  1. dbProviderFactory.CreateConnection()
  2. dbProviderFactory.CreateCommand()
  3. dbProviderFactory.CreateDataAdapter()
  4. dbProviderFactory.CreateParameter()
Pour illuster son utilisation on peut dire que les deux expressions suivantes sont similaires, ou presque :
System.Data.SqlClient.SqlConnection myConnection = new SqlConnection(ConnectionString)
et
DbConnection myConnection = dbProviderFactory.CreateConnection();
myConnection.ConnectionString = ConnectionString;
La différence ? La généricité !

La première expression ne peut servir QUE dans le cas d'une base de donnée Sql Server.
La deuxième expression peut servir pour tous les providers présents sur votre machine.

Nous allons de notre coté implémenter notre fabrique, nous avons tous les éléments pour le faire, contenus dans les chaines de connexion.

Implémentation de la fabrique de classe dans notre classe générique

J'ai choisi de créer une propriété publique pour accéder à notre variable dbProviderFactory qui, elle, est privée.
La récupération des chaines de connexions se fait dans le constructeur de notre classe. Cette récupération n'aura lieu qu'une seule fois.
Les chaines de connexion récupérées seront stockées dans une variable privée, accessible uniquement dans notre classe d'accés aux données.

On peut compléter le code vu précédemment ainsi :
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Configuration;
using System.Data;
using System.Collections;
using System.Reflection;
using System.Transactions;

namespace GenericAccess
{
    public class Data
    {
        #region Proprits Prives
        private ConnectionStringSettings connectionStringSettings;
        private ConnectionStringSettingsCollection connectionStringsCollection;
        private DbProviderFactory dbProviderFactory;
        #endregion


        #region Proprits Publiques
        public DbProviderFactory DbProviderFactory
        {
            get
            {
                return dbProviderFactory;
            }
        }
        #endregion

        #region Pattern Singleton
        private static Data instance;
        static Data()
        {
   
            // Rcupration de toutes les chaines de connexion
            instance.connectionStringsCollection = ConfigurationManager.ConnectionStrings;

            if (instance.ConnectionStringName == string.Empty)
                instance.ConnectionStringName = instance.connectionStringsCollection[1].Name;

            // Rcupration de la classe fabrique suivant le provider
            instance.dbProviderFactory = DbProviderFactories.GetFactory(
        instance.connectionStringsCollection[1].ProviderName);

        }
        public static Data GetInstance()
        {
            return instance;
        }
        #endregion
    }
}

 
» Démarrer une discussion
 
Discussion démarée par hugues le 06/10/2008 à 13:56, 1 commentaire(s).
Discussion démarée par SonOfGod le 16/06/2009 à 11:57, 1 commentaire(s).