Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

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. Smile 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 :

Publié jeudi 31 décembre 2009 03:50 par Matthieu MEZIL

Commentaires

# re: I autre (meilleur ?) moyen de faire du POCO @ vendredi 1 janvier 2010 00:49

Et si je veux garder mo objet POCO simple dans d'autres couches par exemple ?

Mitsu

# re: I autre (meilleur ?) moyen de faire du POCO @ vendredi 1 janvier 2010 09:25

Pas sûr de comprendre mais si tu veux garder ton objet POCO simple sans y toucher, tu peux mais tu ne bénéficieras pas des fonctionnalités du contexte que j'évoquais au début. A noter que dans ce cas, les modifications seront automatiquement détectées lors du SaveChanges ou lors de l'appel de la méthode DetectChanges.

Ce qu'il faut également voir c'est que je modifie la dll du répertoire de l'exe. Donc si tu utilises la dll de tes entités dans un autre projet, elle ne sera pas modifiée.

Matthieu MEZIL

# re: I autre (meilleur ?) moyen de faire du POCO @ mardi 5 janvier 2010 11:39

Bonne année Matt !!!

Grace à toi j’ai fait connaissance avec  Cecil, et je n’ai rien à dire techniquement sur ton post.

Mais je ne partage pas tes critiques : le faite que l’entité ne doit pas être sealed ou doit être public, c’est un contrainte Nhibernate mais une entité business est amenée à évoluer dans le temps avec le métier et en plus qu’est ce qu’on peut faire avec des entités qui ne sont pas public, normalent toutes les couches techniques et business gravitent autour des entités du domaines.

Pour les Get et surtout les Set, c’est contraignent, car on veut  limiter la responsabilité de modification aux classes business (j’aime pas trop cette approche) ou plutot au code métier des entités.

Pour le constructeur par défaut, c’est une vraie limitation, mais on peut facilement la détourner en limitant la création des entités à des factories (pas dans le sens pattern).

Et finalement, pour le virtual, Hibernate en Java n’a pas cette problématique car tous est virtuel en Java par défaut. Je trouve que placer une propriété en virtuel ne pose pas de problème si on sait ce qui va se passer derrière.

La dernière remarque d’ordre déontologique est  ce qu’il vaut mieux utiliser un pattern connu « proxy » ou plutôt modifier le code de l’assembly ?  

rochdi

# re: I autre (meilleur ?) moyen de faire du POCO @ mardi 5 janvier 2010 13:05

Une petite précision concernant le virtual en NHibernate. Il y a une raison pour laquelle NHibernate force tous les membres d'une entité d'être en virtual et ce n'est pas par plaisir ou parce qu'en Java c'était comme ça. C'est pour permettre de faire du "vrai" POCO. Sinon comment intercepter les méthodes et les propriétés ?

tja

# re: I autre (meilleur ?) moyen de faire du POCO @ mardi 5 janvier 2010 23:55

@ Rochdi :

"qu’est ce qu’on peut faire avec des entités qui ne sont pas public"

Une entité non public peut malgré tout être exposé via une interface.

"Je trouve que placer une propriété en virtuel ne pose pas de problème si on sait ce qui va se passer derrière"

C'est bien là le problème. On ne maîtrise pas le code derrière.

"La dernière remarque d’ordre déontologique est  ce qu’il vaut mieux utiliser un pattern connu « proxy » ou plutôt modifier le code de l’assembly ?"

Modifier l'assembly pose des problèmes : par exemple, le fait de perdre le debug car les pdb ne sont plus bons. Inversement, contrairement au Proxy, c'est une approche plus performante et non contraignante.

Matthieu MEZIL

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01