7
votes

Stratégies de remplacement de la couche de données héritées avec cadre d'entité et classes de POCO

Nous utilisons .NET C # 4.0, VS 2010, EF 4.1 et code hérité dans ce projet sur lequel nous travaillons.

Je travaille sur un projet de formulaire WIN où j'ai pris la décision de commencer à utiliser l'entité Framework 4.1 pour accéder à une DB MS SQL. La base de code est assez ancienne et nous avons une couche de données existante qui utilise des adaptateurs de données. Ces adaptateurs de données sont utilisés partout sur la place (dans les applications Web et des applications de formulaire Win) Mon plan consiste à remplacer l'ancien code d'accès à la base de données avec EF au fil du temps et éliminez le couplage serré entre les couches d'interface utilisateur et la couche de données.

Mon idée est donc de combiner plus ou moins de combiner EF avec la couche d'accès à des données héritées et remplacez lentement la couche de données héritées avec une prise plus moderne sur les choses en utilisant EF. Donc, pour l'instant, nous devons utiliser EF et le code d'accès à la DB hérité.

Ce que j'ai fait jusqu'à présent, c'est ajouter un projet contenant le fichier et le contexte EDMX. L'EDMX est généré à l'aide d'une première approche de base de données. J'ai également ajouté un autre projet contenant les classes de POCO (en utilisant ADO.net Poco Entity Generator). J'ai plus ou moins suivi l'approche de Julia Lerman dans son livre "Cadre d'entité de programmation" sur la manière de scinder le modèle et les classes de POCO générées. Le modèle de base de données a été défini depuis des années et ce n'est pas une option, le changement de table et des relations, des déclencheurs, des procédures stockées, etc., donc je suis essentiellement bloqué avec le modèle de DB tel qu'il est.

J'ai lu sur le motif de référentiel et l'unité de travail et je suis un peu comme les motifs, mais j'ai du mal à les mettre en œuvre lorsque j'ai à la fois EF et le code d'accès Legacy DB à traiter. Spécialement quand je n'ai pas le temps de remplacer tout le code d'accès DB hérité de la DB avec une implémentation pure EF. Dans un monde parfait, je recommencerais à nouveau avec un nouveau type de données, mais ce n'est pas une option ici.

Le référentiel et l'unité de travail sont-ils la voie à suivre ici? Afin d'utiliser les classes de POCO dans ma couche d'entreprise, je dois parfois utiliser EF et le code DB Legacy pour peupler mes classes de POCO. Dans d'autres mots, je peux parfois utiliser EF pour récupérer une partie des données dont j'ai besoin et utiliser l'ancienne couche d'accès à la DB pour récupérer le reste des données, puis cartographier les données sur mes classes de POCO. Lorsque je souhaite mettre à jour des données, je dois choisir des données à partir des classes POCO et utiliser le code d'accès des données hérité pour stocker les données de la base de données. J'ai donc besoin de cartographier les données extraites de la couche d'accès aux données héritées sur mes classes POCO lorsque je souhaite afficher les données de l'interface utilisateur et inversement lorsque je souhaite enregistrer des données sur la base de données.

Compliquer les choses que nous stockons des données dans des tables que nous ne connaissons pas le nom de Avant-Runtime (ne me demandez pas pourquoi :-)). Donc, dans l'ancienne couche d'accès à la DB, nous avons dû créer des instructions SQL à la volée où nous avons inséré les noms de table et de colonne basés sur des informations provenant d'autres tables.

Je trouve également que les relations entre les classes de POCO sont un peu trop centrées sur la base de données. Dans d'autres termes, je pense que je dois avoir un modèle de domaine plus simplifié pour travailler. Je devrais peut-être créer un modèle de domaine qui correspond à la facture puis utiliser les classes de POCO comme "DAO" pour remplir les classes de modèle de domaine?

Comment implémenteriez-vous cela à l'aide du motif de référentiel et de l'unité de modèle de travail? (Si tel est le moyen d'aller)


0 commentaires

3 Réponses :


3
votes

Générateur de classe EDMX + POCO Résultats dans le code EFV4, pas de code EFV4.1 mais vous n'avez pas à vous soucier de ces détails. EFV4.1 offre juste une API différente qui fait exactement la même (et elle est seulement wrapper autour de l'API EFV4).

Selon la manière dont vous utilisez des jeux de données, vous pouvez atteindre des problèmes très difficiles. Les jeux de données sont une représentation du modèle de changement de jeu. Ils savent quels changements ont été effectués aux données et ils sont capables de stocker de ces changements. Les entités EF savent que ceci uniquement s'ils sont attachés au contexte qui les ont chargés de la base de données. Une fois que vous avez travaillé avec des entités détachées, vous devez faire un grand effort pour dire à EF ce qui a changé - Surtout lors de la modification des relations (entités détachées sont des scénarios courants dans des applications Web et des services Web). Pour ces objectifs, EF propose un autre modèle appelé Entités auto-suivantes mais ils ont Un autre problème et limitations ( Par exemple, le chargement paresseux manquant, vous ne pouvez pas appliquer des modifications lorsque l'entité avec la même clé est jointe au contexte, etc.).

ef ne prend pas également en charge plusieurs fonctionnalités utilisées dans les jeux de données - par exemple Keys uniques et mises à jour de lot < / a>. C'est amusant que les API de MS plus récentes résolvent généralement certaines douleurs des API précédentes, mais fournissent dans le même temps beaucoup moins de fonctionnalités que les API précédentes introduisant de nouvelles douleurs.

Un autre problème peut être avec la performance - EF est plus lent, puis une accès directe de données avec des jeux de données et une consommation de mémoire supérieure (et oui des fuites de mémoire signalées).

Vous pouvez oublier d'utiliser EF pour accéder aux tables que vous ne connaissez pas au moment de la conception. EF n'autorise aucun comportement dynamique. Les noms de table et le type de serveur de base de données sont fixés dans la cartographie. Un autre problème peut être avec la manière dont vous utilisez des déclencheurs - Orm Tools n'aiment pas les déclencheurs et EF a des fonctionnalités limitées lorsque vous travaillez avec des valeurs calculées de base de données (possibilité de remplir la valeur dans la base de données ou dans l'application est disjonctive).

Le moyen de remplir les pocos des jeux de données EF + sonne comme celui-ci ne sera pas possible lorsque vous utilisez uniquement EF. EF a des modèles de mappage autorisés, mais des possibilités de mapper plusieurs tables à une seule classe de POCO sont extrêmement limitées et limitées (si vous souhaitez avoir ces tables modifiables). Si vous voulez simplement charger une entité de EF et une autre entité à partir de l'adaptateur de données et simplement de faire référence entre eux, vous devez être correct - dans ce référentiel de scénario sonne comme un motif raisonnable car le but du référentiel est exactement ceci: chargez ou persistez des données. Unité de travail peut également être utilisable car vous voudrez probablement réutiliser une connexion de base de données unique entre EF et les adaptateurs de données afin d'éviter une transaction distribuée lors de la sauvegarde des modifications. UOW sera le lieu responsable de la manipulation de cette connexion.

La mappage EF est liée à la conception de la base de données - vous pouvez introduire des modifications orientées objet, mais toujours EF dépend étroitement de la base de données. Si vous souhaitez utiliser un modèle de domaine avancé, vous aurez probablement besoin de classes de domaine distinctes de EF et de jeux de données. Encore une fois, il incombera au référentiel de cacher ces détails.


3 commentaires

Merci! Superbe réponse :) Je pensais écrire mes propres classes de mappage pour traduire les entités de jeu de données EF + sur mes entités modèles de domaine et vice versa. Si cette cartographie soit effectuée dans les classes de référentiel afin que les méthodes renvoient des entités de modèle de domaine ou que cela devrait être effectué dans les classes qui utilise les classes de référentiel?


Je pense que cela relève de la responsabilité des référentiels.


Je me débats un peu avec ma mise en œuvre du référentiel. J'ai déclaré un document de classe comme une racine agrégée (dans mon modèle de domaine) et j'ai un document documentaire qui hérite d'un référentiel générique avec les méthodes standard telles que Get, Getall, Insérer, Supprimer, Enregistrer. À l'intérieur de la classe DocumentRepository, j'utilise EF et EF a généré des entités poco ignorantes persistantes pour moi que je prévois d'utiliser à l'intérieur du référentiel (Overkill?). Comment implémenteriez-vous dire DOCUMAYREPOSITORY.GETALL (Objet de spesification)? Getall () doit renvoyer une liste de documents (objet de domaine). Merci!



5
votes

Les cloches d'alarme sonnent pour moi! Nous avons essayé de faire quelque chose de similaire il y a un moment (seulement avec NHibernate pas EF4). Nous avons eu plusieurs problèmes à exécuter ADO.NET le long d'une oubli de la base de données en étant un grand.

Le modèle de base de données a été défini pour années et ce n'est pas une option la changer la table et le relations, déclencheurs, stockés procédures, etc., donc je suis fondamentalement bloqué avec le modèle de base de données tel qu'il est.

Yep. Même chose! Le problème était que nos Procs stockés contenaient beaucoup de logiques commerciales et n'étaient pas simples processus de crud, ce qui permet de mettre à jour l'ORM avec les différentes mises à jour effectuées par une procédure stockée n'était pas facile du tout - principe de responsabilité unique - pas une bonne chose à briser !

Mon plan est de remplacer l'ancien dB Code d'accès avec ef au fil du temps et obtenir débarrasser pour le couplage serré de
entre les couches d'interface utilisateur et la couche de données.

Peut-être que vous pourriez découpler sans la nécessité d'un orj - que diriez-vous de mettre en place une couche de service / façade en face de votre couche d'interface utilisateur pour coordonner toutes les interactions avec le domaine sous-jacent et la cacher à partir de l'interface utilisateur.

Si votre base de données est «roi» et votre application est fortement pilotée, je pense que vous allez toujours vous battre une bataille en montée en mettant en œuvre les modèles que vous mentionnez.

Embrace Ado.net pour ce projet - Utilisez des modèles EF4 et DDD sur votre prochain champ Vert Proj :)


2 commentaires

Bonne réponse! Il est toujours bon d'entendre des personnes qui ont été dans la "guerre" et vivaient pour dire au conte :)


Oui, je suis d'accord sur lequel suivre le troupeau avec EF n'est pas toujours une balle d'argent. Vous vaut vraiment la peine de cacher tout derrière une couche de service (comme suggéré), de sorte que au moins l'interface utilisateur est empêchée du bruit et de la logique commerciale est enveloppée.



0
votes

De combien nous avons mis en œuvre, j'ai appris les choses suivantes.

  1. Les objets POCO et auto-suivi sont difficiles à traiter, comme si vous n'avez pas la compréhension facile de ce qui se passe à l'intérieur, il y aura un certain nombre de comportements inattendus qui peuvent avoir bien fonctionné dans votre projet précédent.
  2. Modification du modèle n'est pas facile, jusqu'à présent, nous avons géré le crud simple sans unité de travail et modèle de carte d'identité. Maintenant, beaucoup de code hérité que nous avons écrit dans le passé ne considère pas ces nouveaux modèles et la logique ne fonctionnera pas correctement.
  3. Dans notre code précédent, nous utilisions simplement des transactions et une seule instruction d'insertion / mise à jour / Supprimer directement envoyée à la base de données en supposant que les transactions sur le côté serveur s'occuperont de toutes les opérations.
  4. Dans de telles conditions, nous traitons directement des identifiants tout le temps, les identifiants nouvellement générés ont été immédiatement disponibles après une déclaration d'insertion unique, mais ce n'est pas cas avec EF.
  5. En EF, nous ne traitons pas d'IDS, nous avons affaire à des propriétés de navigation, qui constitue un changement énorme des méthodes de programmation ADO.NET précédentes.
  6. De notre expérience, nous avons constaté que seulement remplacer EF avec un code d'accès antérieur des données entraînera un chaos. Mais les services EF + RIA vous offrent une solution complètement nouvelle dans laquelle vous obtiendrez probablement tout ce dont vous avez besoin et que votre interface utilisateur vous lie très facilement. Donc, si vous envisagez de réécrire complète en utilisant UI + RIA Services + EF, alors cela vaut la peine, car beaucoup de dépendance dans la gestion de la requête réduit automatiquement. Vous ne vous concentrerez que sur la logique commerciale, mais c'est une décision importante et la quantité d'heures de travail requises en réécriture complète ou simplement remplacer EF est presque la même.
  7. Nous sommes donc allés UI + RIA Services + EF Way, et nous avons commencé à remplacer un module unique. La plupart du temps, EF coexistera facilement avec votre infrastructure existante afin qu'il n'y ait pas de mal.

1 commentaires

Merci pour votre réponse! Grandement apprécié!:)