2009-07-10 9 views
3

Supposons que je suis la conception d'une classe qui peut gérer toute la technologie de base de données pour créer une connexion, exécuter la commande et récupérer des données, etc.C# - Une classe pour la connexion de base de données générique, commande, lecteur

Si je dois créer un classe de gestion de base de données générique pour les SGBDR existants (comme SQL Server, Oracle, FireBird, etc.), que .net abstract-class/Interface dois-je utiliser {DbConnection, DbCommand, DbParameter, ...} ou {IDbConnection, IDbCommand, IDbParameter, ...}?

Dois-je utiliser le code comme

public bool CreateConnection(DatabaseTypeEnum type) 
{ 
    DbConnection conn ; 

    if(type==DatabaseTye.Oracle) 
    { 
     //.... 
    }  
} 

public DbDataReader GetData() 
{ 

    DbCommand comm; 
    //... 
} 

ou,

public bool CreateConnection(DatabaseTypeEnum type) 
{ 
    IDbConnection conn ; 

    if(type==DatabaseTye.Oracle) 
    { 
     //.... 
    } 
} 

public IDbDataReader GetData() 
{ 

    IDbCommand comm; 
    //... 
} 

Et, Pourquoi?

+0

Vous voulez dire: Quand dois-je créer un générique ...? et pourquoi? –

+0

Veuillez voir la question mise à jour. –

+0

Faites attention à l'utilisation du mot 'Generic' quand vous parlez de C#, car il a une signification très spécifique sans rapport avec cette question. – CaptainCasey

Répondre

5

Ermm ... tout autre question :)

OK, ni ...

Vous allez ouvrir la liste fermer violer le principe quand vous faites cela ... Le commutateur/instruction if en ce particulier endroit me rend mal à l'aise :). Je laisserais la création réelle à une classe Factory et votre code ne devrait pas se soucier s'il parle à un SQL Server ou DB2 ou Oracle ou quoi que ce soit.

Idéalement, votre code devrait seulement parler à IDbConnection, IDbCommand, etc. ou à la classe de base abstraite (DbConnection, DbCommand, etc.). Parfois, je trouve que vous avez besoin d'upcast à un fournisseur spécifique tho (comme SqlDataReader pour l'utilisation de méthodes spécifiques), mais il est assez rare.

L'usine encapsulera cette instruction switch/if dans un seul endroit afin de la maintenir facilement. Vous pouvez en outre résumer la création réelle dans un app.config. Ainsi, dans app.config, vous choisissez le type de backend DB que vous supportez et Factory le récupère à partir de là et crée les DBs nécessaires pour vous.

Voir: this. Lisez à propos de Création de DbProviderFactory et de la partie Connexion ...

+0

+1 de moi. En usine, j'utilise providerName dans la chaîne de connexion pour mapper vers un providerSettings pour des choses spécifiques au fournisseur comme les préfixes de paramètres (par exemple "@" pour MSSQL, ":" pour Oracle, etc.). – devstuff

0

Pourquoi n'utilisez-vous pas de génériques?

Vous pouvez définir votre classe comme celui-ci par exemple:

public class DBHelper<T, Y, W> where T: DbConnection, new() where Y : DbCommand, new() 
{ 
     private T conn_ = new T(); 
     private Y comm_ = new Y();    
} 

C'est ce que je fais pour et son vraiment facile à entretenir.

+0

Comment cela fonctionnerait-il en code réel, pouvez-vous l'expliquer? – theJerm

+0

Vous n'avez pas besoin de paramètre de type Y ici puisque DbCommand peut être instancié à partir de l'objet de connexion, comme conn.CreateCommand(). Aussi, quel est le paramètre de type W pour? – nawfal

0

Vous devez utiliser les IDbConnection et IDbCommand puisque les différents fournisseurs de bases de données auront différentes implémentation des interfaces (pour leur chose ADO.NET), mais mieux pas exactement comme vous avez posté. Vous devriez plutôt rendre toute la classe générique pour prendre en charge les génériques IDbConnection et IDbCommand. Peut être comme ceci:

public class Db<T> where T : IDbConnection, new() 
{ 
    public bool CreateConnection() 
    { 
     T conn; 

     //now you dont need these lines since you dont have to worry about 
     //what type of db you are using here, since they all implement 
     //IDbConnection, and in your case its just T. 
     //if(type==DatabaseTye.Oracle) 
     //{ 
      //.... 
     //} 
    } 

    public DbDataReader GetData() 
    { 
     //get comm object from S conn 
     using(var conn = new S()) 
      using (var comm = conn.CreateCommand()) 

     //... 
    } 

L'avantage est que vous pouvez passer à cette classe les types que vous souhaitez utiliser pour DbConnection et DbCommand qui sera différent pour connecteur .net MySQL et un Oracle. Donc vous avez une sorte de contrôle de l'extérieur de la classe. Vous pouvez voir à ce question and my answer pour référence pour une implémentation de base.

Questions connexes