I autre (meilleur ?) moyen de faire du POCO
Si vous voulez travailler avec des entités POCO et garder dans le même temps les fonctionnalités du contexte comme le tracking des modifications, l’attachement automatique des entités liées, le lazy loading, EF va générer un proxy qui hérite de vos entités (un proxy par entité) et qui va ajouter le code pour faire cela. C’est le même fonctionnement qu’avec N-Hibernate. Cependant, je pense que c’est vraiment pas terrible comme approche. En effet, c’est super contraignant : vos entités ne doivent pas être sealed et doivent être public, tous vos get et set doivent être protected ou public et virtual, il faut avoir un constructeur public ou protected sans paramètre. A cuase de ces contraintes, je n’aime pas cette approche.
Je ne pense (j’espère) d’ailleurs ne pas être le seul dans ce cas. Maintenant c’est facile de critiquer mais comment faire mieux ?
Mon idée était de modifier directement l’assembly des entités plutôt que de passer par des proxy qui en héritent. Sur les conseils de Simon, j’ai utilisé Cecil pour cela.
Comment ça marche ?
J’ai défini un programme qui prend deux paramètres dans la méthode Main : le chemin de l’assembly initial et le chemin de l’edmx. Dans mon program, j’injecte de l’IL dans mes entités afin de leur faire implémenter INotifyPropertyChanging, INotifyPropertyChanged, IEntityWithChangeTracker, IEntityWithKey et IEntityWithRelationships.
Je vais vous épargnez l’IL, ça m’évitera les commentaires du style OMG.
Cependant, je vous invite à télécharger le code si cela vous intéresse.
Ensuite, dans mon application, j’utilise le post-build event suivant :
"D:\Documents\Visual Studio 2010\Projects\EF POCO with Cecil\EFPOCOWithCecil\bin\Release\EFPOCOWithCecil.exe" "$(TargetDir)Entities.dll" "$(ProjectDir)..\DAL\Northwind.edmx"
Avec cette implémentation, je peux profiter des fonctionnalités du contexte.
Je n’ai qu’une seule restriction : les navigation properties de type collection doivent être définies comme des ICollection<T> (c’est pareil avec EF mais ça ne me choque pas contrairement aux contraintes que j’évoquais au début).
Le bon point avec cette façon de faire est le fait je n’ai plus les contraintes des proxies. De plus, avec EF, si vous utilisez la méthode CreateObject du contexte, vous allez avoir une instance du proxy. Si vous utilisez le constructeur directement , vous n’allez pas avoir une instance du proxy mais de votre propre classe (donc vous perdez les fonctionnalités du contexte). Ce point est un peu perturbant pour les développeurs débutant. Avec mon approche, ce problème est également résolu.
Vous pouvez télécharger mon code ici.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :