2010-09-09 4 views
6

Je suis confronté à plusieurs problèmes en essayant d'appliquer DDD avec EF4 (dans le contexte ASP MVC2). Votre avis serait grandement apprécié. Tout d'abord, j'ai commencé à utiliser POCO car la dépendance sur ObjectContext n'était pas très confortable dans beaucoup de situations.Comment gérez-vous DDD et EF4

Aller à POCO a résolu quelques problèmes mais l'expérience n'est pas ce à quoi j'étais habitué avec NHibernate.

Je voudrais savoir s'il est possible d'utiliser designer et de générer non seulement des entités mais aussi des objets de valeur (ComplexType?). Si je veux dire Valeur objet est une classe avec un ctor sans toutes les propriétés de jeu (modification T4 nécessaire?). Le seul moyen que j'ai trouvé pour ajouter du comportement aux entités anémiques est de créer des classes partielles qui étendent celles générées par edmx. Je ne suis pas satisfait de cette approche.

Je ne sais pas comment créer plusieurs dépôts avec un edmx. Pour l'instant j'utilise une classe partielle pour regrouper les méthodes pour chaque agrégat. Chaque groupe est un référentiel en fait.

La dernière question concerne IQueryable. Devrait-il être exposé à l'extérieur du référentiel? Si je me réfère au livre ble, le référentiel devrait être une unité d'exécution et ne devrait pas exposer quelque chose comme IQueryable. Qu'est-ce que tu penses ?

Merci pour votre aide.

Thomas

+1

En ce qui concerne la question IQueryable, voir ceci: http://stackoverflow.com/questions/1699607/asp-mvc-repository-that-reflects-iqueryable-but-not-linq-to-sql-ddd-how-to -ques/1699756 # 1699756 –

Répondre

0

Cela fait un certain temps que j'ai posé cette question et j'ai eu l'occasion de le faire moi-même.

Je ne pense pas que ce soit une bonne pratique d'exposer IQueryable du tout en dehors de la couche DAL. Il apporte plus de problèmes qu'il résout. Je parle de grandes applications MVC. Tout d'abord, les refactorings sont plus difficiles, de nombreux développeurs utilisent des instances IQueryable à partir des vues et après avoir lutté avec le fait que lors de la résolution de IQueryable la connexion était déjà éliminée. Problèmes de performance car toute la base de données est souvent interrogée pour un ensemble donné de résultats et ainsi de suite.

Je préfère exposer Ienumerable de mes dépôts et croyez-moi, cela me sauve beaucoup de problèmes.

4

Il est bon d'utiliser Poços, mais notez que EntityObject ne nécessite pas ObjectContext.

Oui, les types complexes sont des objets de valeur et oui, vous pouvez les générer dans le concepteur. Sélectionnez plusieurs propriétés d'une entité, faites un clic droit et choisissez refactor dans un type complexe.

Je recommande fortement de mettre les méthodes métier dans leurs propres types, pas sur les entités. Les types "anémiques" peuvent être un problème si vous devez les maintenir, mais quand ils sont codés, ils ne sont pas un problème d'entretien. La séparation de la logique métier des types d'entités permet à vos règles métier et à votre modèle de données d'évoluer de manière indépendante. Oui, vous devez utiliser des classes partielles si vous devez mélanger ces préoccupations, mais je ne crois pas que séparer votre modèle et vos règles est une mauvaise chose.

Je pense que les dépôts devraient exposer IQueryable, mais vous pouvez faire un bon cas que services de domaine ne doit pas. Les utilisateurs essaient souvent de créer leurs référentiels dans les services de domaine, mais souvenez-vous que le référentiel n'existe que pour éliminer la persistance. Des préoccupations comme la sécurité devraient être dans les services de domaine, et vous pouvez faire valoir qu'ayant IQueryable là donne trop de pouvoir au consommateur.

+0

Merci pour votre réponse. Généralement, je mets des méthodes comportementales évidentes aux entités. Quand ce n'est pas évident, je crée un service pour ça. Comment résolvez-vous ce point? Si les dépôts exposent IQueryable, il n'y a aucune garantie qu'il sera éliminé à tout moment ou s'il est éliminé, il y aura un problème lors de la conversion de Iqueryable en List ou Enumarable car la connexion sera déjà fermée. –

+0

En ce qui concerne l'élimination des connexions, la face publique de mes services de domaine est une unité d'objet de travail. L'unité de travail implémente IDisposable. L'unité de travail conserve une référence privée à une instance ObjectContext transmise aux référentiels via l'injection du constructeur. Dans mon cas, l'unité de travail est consommée par les contrôleurs ASP.NET MVC, qui ne sont pas eux-mêmes disposés avant que les vues aient été rendues, etc. Il est donc naturel de disposer de tout au bon moment; Je n'ai jamais à y penser. –

+0

En ce qui concerne où mettre des méthodes d'affaires, je trouve beaucoup plus naturel de tout mettre dans les services de domaine plutôt que dans les services de domaine et d'autres dans des endroits différents. Ceci est particulièrement important lorsque vous utilisez des services de données tels que les services de données ADO.NET/Astoria. –

1

Je pense que c'est OK pour exposer IQueryable à l'extérieur du référentiel, seulement parce que ne pas le faire pourrait être inutilement restrictif. Si vous n'exposez des données que par le biais de méthodes telles que GetPeopleByBirthday et GetPeopleByLastName, que se passe-t-il lorsque quelqu'un recherche un individu par son nom de famille et? Tirez-vous dans toutes les personnes avec le nom de famille "Smith" et faire une recherche linéaire pour l'anniversaire que vous voulez, ou créez-vous une nouvelle méthode GetPeopleByBirthdayAndLastName? Qu'en est-il du pauvre malheureux qui doit mettre en place un formulaire QBE?À l'époque où la seule façon de faire des requêtes ad hoc sur le domaine était de générer du SQL, le seul moyen de se protéger était de proposer des méthodes spécifiques pour récupérer et modifier les données. Maintenant que nous avons LINQ, il n'y a aucune raison de garder les menottes. Tout le monde peut soumettre une requête et vous pouvez l'exécuter en toute sécurité sans souci. Bien sûr, vous pourriez craindre qu'un utilisateur puisse voir les données d'un autre utilisateur, mais cela est facile à atténuer, car vous pouvez restreindre les données que vous donnez. Par exemple:

public IQueryable<Content> Content 
{ 
    get { return Content.Where(c => c.UserId == this.UserId); } 
} 

Cela fera en sorte que les seules Content lignes que l'utilisateur peut obtenir sont ceux qui ont son UserId. Si votre problème concerne la charge de la base de données, vous pouvez par exemple examiner les expressions de requête pour les analyses de table (accès aux tables sans clause Where ou sans colonnes indexées dans la clause Where). Certes, ce n'est pas trivial, et je ne le recommanderais pas.