IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Repository pattern et clause Where


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2008
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2008
    Messages : 97
    Par défaut Repository pattern et clause Where
    Bonjour à tous,

    j'écris une application winform, et j'aimerais bien séparer la couche d'accès aux données, histoire que ça soit bien propre dès le départ.

    J'utilise une base de donnée MySQL et n'utilise pas Linq (.Net 2.0 oblige)

    je me suis donc penché sur le repository pattern.

    Sur internet il y a plusieurs tutoriaux mais en général ils ne présentent que les cas simples où on veut récupérer toute la table.
    Et donc dans leur cas, fastoche, toutes les classes Repository implémentent une interface générique IRepository<T> du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      public interface IRepository<T>
      {
        IList<T> SelectAll();
        ...
      }
    ce que j'implémenterais comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
       public class UserSQLRepository : IRepository<User>
        {
            #region membres publics
     
            public UserSQLRepository(IDbConnection dbConnection)
            {
                if (null == dbConnection)
                {
                    throw new ArgumentNullException("dbConnection");
                }
                m_dbConnection = dbConnection;
            }
     
            public List<User> SelectAll()
            {
                using (IDbCommand command = m_dbConnection.CreateCommand())
                {
                    // je remplis et retourne ma liste complète avec un "Select * From Users"
                }
            }
     
            #endregion
     
            #region membres privés
     
            private IDbConnection m_dbConnection;
     
            #endregion
        }
    Ma question est: si je n'ai besoin de récupérer que certains utilisateurs suivant certains critères, quelle est la bonne manière de faire passer à une méthode l'expression permettant de filtrer ma requête sql?

    J'ai vu plusieurs solutions mais quelle est la meilleure?

    solution 0.

    faire une méthode SelectAll(string critères)

    solution 1.

    ne plus créer une interface générique mais faire une interface par classe repository avec chacune leurs méthodes de sélections en fonction de ce que je veux récupérer dans la table.

    SelectByName(string[] names)

    solution 2.

    faire un truc du genre que j'ai vu sur le net:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
      public interface IRepository<T>
      {
        IList<T> SelectAll();
        IList<T> SelectAll(Func<T, bool> expression);
      }
     
      public class CustomersRepository : IRepository<Customer>
      {
        public IList<Customer> SelectAll()
        {
          return new List<Customer>
          {
            new Customer{ Id = 1, Name = "Customer1"},
            new Customer{ Id = 2, Name = "Customer2"},
            new Customer{ Id = 3, Name = "Customer3"},
            new Customer{ Id = 4, Name = "Customer4"}
          };
        }
     
        public IList<Customer> SelectAll(Func<Customer, bool> expression)
        {
          return new List<Customer>
          {
            new Customer{ Id = 1, Name = "Customer1"},
            new Customer{ Id = 2, Name = "Customer2"},
            new Customer{ Id = 3, Name = "Customer3"},
            new Customer{ Id = 4, Name = "Customer4"}
          }.Where(expression).ToList();
        }
      }

    l'exemple utilise linq (Where) mais je peux l'adapter en utilisant un predicate.
    Mais ce qui me chiffonne, c'est que si j'ai 20000 enregistrements, je devrais tous les charger de la base de donnée et les filtrer seulement dans la liste.

    Qu'est ce qu'il faut faire pour que ça soit, maintenable, sûr et beau?

  2. #2
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Personnellement, je ferais un truc du genre :

    -> Méthode Select(Filter)
    Avec filter = dictionnaire avec cle = nom du champ, et valeur = valeur du filtre
    Découpage du dictionnaire pour générer un order "where" générique.

    -> La méthode SelectAll appelle Select() avec un Filter null.

    On peut même aller plus loin et imaginer un mapping entre noms des tables et nom des objets de ton programme.

    Ainsi, le Select() reste générique pour tous les T en faisant un select T.Name

  3. #3
    Membre éprouvé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2008
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2008
    Messages : 97
    Par défaut
    Merci pour la réponse,

    Dans un premier temps je pense que je suis bien parti pour suivre ton idée du dictionnary.

    Par contre je n'ai pas bien saisi l'idée du mapping objet-table... je ne vois pas bien comment ça règlerait le problème de filtrage de requete.


    Je me demande comment je ne trouve pas de méthode bien établie, le problème de la couche d'accès aux données ne date pas de .NET 3.5 qui est encore "récent", puis c'est quand même rare qu'un programme ne fasse pas des requêtes sql filtrées comment les entreprises de développement font concrètement?

  4. #4
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Le mapping objet-table n'est pas là pour t'aider à faire des filtres, mais simplement pour te permettre d'utiliser la même classe quelle que soit la table lue, sans devoir te trimballer des noms de table dans ton code.

    C'est juste une idée que j'ai mis en place dans un petit projet perso, ce qui m'a permis de ne pas avoir besoin de toucher à la couche d'accès aux données, même après avoir rajouter des tables/vues.

  5. #5
    Membre éprouvé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2008
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2008
    Messages : 97
    Par défaut
    Le problème du dictionary c'est qu'il est difficile de stocker simplement à la foi l'opération, le type, le nom et la valeur.

    Ca ne me dérange pas de faire une classe en plus gérant tout ça mais ce que je souhaitais avant de m'embarquer dans quelque chose c'est savoir si il n'y avait pas une méthode, un pattern, une manière de faire conseillée ou des manière de faire déconseillées.

    Comment vous, les professionnels du C#, faites dans les entreprises?

  6. #6
    Nouveau candidat au Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 2
    Par défaut
    Pourquoi ne pas simplement ajouter des methodes avec parametres normaux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public List<User> SelectByName(string patternName)
    {
       using (IDbCommand command = m_dbConnection.CreateCommand())
       {
          // tu remplis et retourne ma liste complète avec un 
          string req = "Select * From Users where name like '%" + patternName + "%'";
       }
    }

Discussions similaires

  1. [super requete] Dumper un model avec une clause where
    Par elievar dans le forum Langage SQL
    Réponses: 3
    Dernier message: 16/03/2005, 17h05
  2. Ordre des tests dans la clause WHERE
    Par Tans98 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 22/09/2004, 10h52
  3. Problème clause WHERE
    Par Invité dans le forum Langage SQL
    Réponses: 3
    Dernier message: 11/06/2004, 15h07
  4. probleme avec le caractere 'Z' dans ma clause WHERE
    Par dibox dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 01/04/2004, 12h21
  5. [ character en simple cote ] clause Where
    Par hocinema dans le forum DB2
    Réponses: 3
    Dernier message: 20/02/2004, 10h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo