Je pense que si vos référentiels utilisent un ORM, il est déjà suffisamment extrait de la base de données.
Cependant, là où je travaille maintenant, quelqu'un pense que nous devrions avoir une couche qui résume l'ORM au cas où nous souhaiterions changer l'ORM plus tard.
Est-ce vraiment nécessaire ou c'est simplement beaucoup de travail pour créer une couche qui fonctionnera sur de nombreux ORM?
Éditer
Juste pour donner plus de détails:
- Nous avons des classes POCO et Entity Class qui sont mappées avec AutoMapper. La classe d'entité est utilisée par la couche Repository. La couche de référentiel utilise ensuite la couche d'abstraction supplémentaire pour communiquer avec Entity Framework.
- La couche métier n'a en aucun cas un accès direct à Entity Framework. Même sans la couche d'abstraction supplémentaire sur l'ORM, celle-ci doit utiliser la couche de service qui utilise la couche de référentiel. Dans les deux cas, la couche métier est totalement séparée de l'ORM.
- L'argument principal est de pouvoir changer ORM à l'avenir. Puisqu'il est vraiment localisé à l'intérieur de la couche Repository, pour moi, il est déjà bien séparé et je ne vois pas pourquoi une couche d'abstraction supplémentaire est nécessaire pour avoir un code "de qualité".
Réponses:
De cette façon réside la folie. Il est très peu probable que vous ayez besoin de changer d'ORM. Et si jamais vous décidez de changer l'ORM, le coût de réécriture des mappages sera une infime fraction du coût de développement et de maintenance de votre propre méta-ORM. Je m'attendrais à ce que vous puissiez écrire quelques scripts pour faire 95% du travail nécessaire pour changer d'ORM.
Les cadres internes sont presque toujours une catastrophe. En construire un en prévision des besoins futurs est presque une catastrophe garantie. Les cadres réussis sont extraits de projets réussis, pas construits à l'avance pour répondre à des besoins imaginaires.
la source
L'ORM fournit une abstraction pour que votre couche de données soit indépendante de son SGBDR, mais cela peut ne pas être suffisant pour «délier» votre couche métier de votre couche de données. Plus précisément, vous ne devez pas laisser les objets mappés aux tables SGBDR se «répandre» directement dans la couche de gestion.
À tout le moins, votre couche métier doit programmer des interfaces que vos objets mappés par table et gérés par ORM de la couche de données pourraient potentiellement implémenter. En outre, vous devrez peut-être créer une couche d'interface de création de requête abstraite pour masquer les capacités de requête natives de votre ORM. Le but principal est d'éviter de "faire entrer" un ORM particulier dans votre solution au-delà de sa couche de données. Par exemple, il peut être tentant de créer des chaînes HQL ( Hibernate Query Language ) dans la couche métier. Cependant, cette décision apparemment innocente lierait votre couche d'entreprise à Hibernate, clouant ainsi l'entreprise et les couches d'accès aux données ensemble; vous devriez essayer d'éviter cette situation autant que possible.
EDIT: Dans votre cas, la couche supplémentaire à l'intérieur du référentiel est une perte de temps: sur la base de votre point numéro deux, votre couche métier est suffisamment isolée de votre référentiel. Fournir une isolation supplémentaire introduirait une complexité inutile, sans avantages supplémentaires.
Le problème avec la construction d'une couche d'abstraction supplémentaire à l'intérieur de votre référentiel est que la "marque" particulière d'ORM dicte la façon dont vous interagissez avec. Si vous créez un wrapper mince qui ressemble à votre ORM, mais sous votre contrôle, le remplacement de l'ORM sous-jacent sera à peu près aussi difficile qu'il le serait sans cette couche supplémentaire. Si, en revanche, vous créez une couche qui ne ressemble en rien à votre ORM, vous devez alors remettre en question votre choix de la technologie de mappage relationnel-objet.
la source
UnitOfWork fournit généralement cette abstraction. C'est un endroit qui doit changer, vos référentiels en dépendent via une interface. Si jamais vous avez besoin de changer O / RM, implémentez simplement une nouvelle UoW dessus. Un et terminé.
BTW, cela va au-delà de la simple commutation O / RM, pensez aux tests unitaires. J'ai trois implémentations UnitOfWork, une pour EF, une pour NH (parce que j'ai en fait dû changer de O / RM à mi-projet pour un client qui voulait le support d'Oracle), et une pour la persistance InMemory. La persistance InMemory était parfaite pour les tests unitaires ou même pour le prototypage rapide avant que je ne sois prêt à mettre une base de données derrière.
Le cadre est simple à mettre en œuvre. Vous avez d'abord votre interface générique IRepository
Et l'interface IUnitOfWork
Vient ensuite le référentiel de base (votre choix s'il doit être abstrait ou non
Implémenter IUnitOfWork est un jeu d'enfant pour EF, NH et In Memory. La raison pour laquelle je retourne IQueryable, c'est pour la même raison, a indiqué Ayende dans son article, le client peut filtrer, trier, grouper et même projeter le résultat à l'aide de LINQ et vous bénéficiez toujours de tout cela du côté serveur.
la source