Je viens de devoir désactiver un ORM et c'était une tâche relativement intimidante, car la logique de requête fuyait partout. Si j'avais déjà eu à développer une nouvelle application, ma préférence personnelle serait d'encapsuler toute la logique de requête (à l'aide d'un ORM) pour la protéger du changement. Le modèle de référentiel est assez gênant à coder et à maintenir, donc je me demandais s'il y avait d'autres modèles pour résoudre le problème?
Je peux prévoir des articles sur le fait de ne pas ajouter de complexité supplémentaire avant qu'elle ne soit réellement nécessaire, d'être agile, etc. mais je ne suis intéressé que par les modèles existants qui résolvent un problème similaire de manière plus simple.
Ma première pensée a été d'avoir un référentiel de type générique, auquel j'ajoute des méthodes selon les besoins à des classes de référentiels de type spécifiques via des méthodes d'extension, mais les tests unitaires des méthodes statiques sont terriblement douloureux. C'EST À DIRE:
public static class PersonExtensions
{
public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep)
{
// logic
}
}
la source
Réponses:
Tout d'abord: un référentiel générique doit être considéré comme une classe de base et non comme des implémentations complètes. Cela devrait vous aider à mettre en place les méthodes CRUD courantes. Mais vous devez toujours implémenter les méthodes de requête:
Seconde:
Ne reviens pas
IQueryable
. C'est une abstraction qui fuit. Essayez d'implémenter cette interface vous-même ou utilisez-la sans connaître le fournisseur de base de données sous-jacent. Par exemple, chaque fournisseur de base de données possède sa propre API pour charger les entités avec impatience. C'est pourquoi c'est une abstraction qui fuit.Alternative
Comme alternative, vous pouvez utiliser des requêtes (par exemple, comme défini par le modèle de séparation commande / requête). CQS est décrit dans wikipedia.
Vous créez essentiellement des classes de requête que vous invoquez:
la grande chose avec les requêtes est que vous pouvez utiliser différentes méthodes d'accès aux données pour différentes requêtes sans encombrer le code. vous pouvez par exemple utiliser un service Web dans un, nhibernate dans un autre et ADO.NET dans un troisième.
Si vous êtes intéressé par une implémentation .NET, lisez mon article: http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/
la source
YourProject.YourDomainModelName.Queries
il sera facile de naviguer.Tout d'abord, je pense que l'ORM est déjà une abstraction suffisamment grande pour votre base de données. Certains ORM fournissent une liaison à toutes les bases de données relationnelles courantes (NHibernate a des liaisons avec MSSQL, Oracle, MySQL, Postgress, etc.). Donc, construire une nouvelle abstraction par-dessus ne me semble pas rentable. En outre, arguant du fait que vous devez "résumer" cet ORM n'a pas de sens.
Si vous voulez toujours construire cette abstraction, j'irais à l'encontre du modèle de référentiel. C'était génial à l'ère du SQL pur, mais c'est assez gênant face à l'ORM moderne. Principalement parce que vous finissez par réimplémenter la plupart des fonctionnalités ORM, comme les opérations CRUD et les requêtes.
Si je devais construire de telles abstractions, j'utiliserais ces règles / modèles
Dans la mise en œuvre concrète, j'utiliserais directement les opérations CRUD d'ORM, sans aucun emballage. Je ferais également des requêtes simples directement dans le code. Mais les requêtes complexes seraient encapsulées dans leurs propres objets. Pour «masquer» l'ORM, j'essayerais d'injecter le contexte de données de manière transparente dans un service / objets d'interface utilisateur et je ferais de même pour interroger les objets.
La dernière chose que je voudrais dire, c'est que beaucoup de gens utilisent ORM sans savoir comment l'utiliser et comment en tirer le meilleur profit. Les personnes recommandant des référentiels sont généralement de ce type.
En tant que lecture recommandée, je dirais le blog d'Ayende , en particulier cet article .
la source
Le problème avec l'implémentation qui fuit est que vous avez besoin de nombreuses conditions de filtre différentes.
Vous pouvez affiner cette API si vous implémentez une méthode de référentiel FindByExample et l'utilisez comme ceci
la source
Pensez à faire fonctionner vos extensions sur IQueryable au lieu d'IRepository.
Pour effectuer un test unitaire:
Aucune moquerie fantaisiste n'est requise pour les tests. Vous pouvez également combiner ces méthodes d'extension pour créer des requêtes plus complexes selon les besoins.
la source
IQueryable
est une mauvaise mère, ou plutôt une interface DIEU. Sa mise en œuvre est très courante et il y a très peu (le cas échéant) de fournisseurs LINQ to Sql complets. b) Les méthodes d'extension rendent impossible l'extension (l'un des principes fondamentaux de la POO).J'ai écrit un modèle d'objet de requête assez soigné pour NHibernate ici: https://github.com/shaynevanasperen/NHibernate.Sessions.Operations
Cela fonctionne en utilisant une interface comme celle-ci:
Étant donné une classe d'entités POCO comme celle-ci:
Vous pouvez créer des objets de requête comme celui-ci:
Et puis utilisez-les comme ceci:
la source