2009-04-15 14 views
2

Je tente de mapper une hiérarchie d'entités à l'aide de NHibernate dont presque tous ont des événements. Lors d'une tentative de construire une usine de session cependant, je reçois des messages d'erreur similaires à ce qui suit:NHibernate exige que les événements soient virtuels?

Core.Domain.Entities.Delivery: méthode remove_Scheduled devrait être virtuelle

Livraison est une entité dans mon modèle de domaine avec un événement appelé Planifiée. Puisque les événements ne peuvent pas être déclarés virtuels, je ne sais pas comment procéder ici. Pourquoi NHibernate aurait-il besoin d'événements virtuels?

Répondre

0

à quoi ressemble votre cartographie? Avez-vous cartographié un événement?

Je n'ai pas rencontré ce problème auparavant, mais, encore une fois, je spécifie toujours l'attribut 'lazy = false' sur ma correspondance de classe, de sorte que mes propriétés ne doivent pas être déclarées comme virtuelles. (Comme je n'aime pas déclarer des propriétés comme virtuel, si mon doesnt modèle d'affaires l'exige)

<class name="MyClass" table="MyTable" lazy="false"> 
</class> 
+0

Je ne pensais même pas qu'il était possible de mapper un événement. Vous spécifiez toujours paresseux = faux? La chose est le chargement paresseux est un must absolu dans ma situation. Spécifier quelles entités charger dans chaque situation serait prohibitif. – Jimit

+0

Je spécifie lazy = false au niveau de la classe. Ce faisant, je n'ai pas besoin de créer mes propriétés virtuelles quand je ne le souhaite pas. L'inconvénient est que NHibernate n'utilise pas les proxies dynamiques lors de la récupération d'objets: par exemple, avec des proxies dynamiques, lors de la récupération d'un objet, NHibernate ne remplira que l'ID de l'objet. Seulement lorsque vous accédez à l'une des propriétés de l'objet, l'objet entier sera chargé. Cela n'affecte cependant pas le chargement paresseux des collections. –

2

Les membres du public doivent être déclarés virtuels si vous utilisez le chargement paresseux parce que NHibernate va créer des objets proxy pour vos entités lors de l'exécution. Donc n'utilisez pas le chargement paresseux ou déclarez simplement l'événement comme virtuel - ce n'est pas si commun, mais c'est possible. NHibernate crée des classes proxy pour toutes les entités chargées paresseuses et les utilise lorsqu'une entité est référencée mais pas encore chargée. L'accès à ce proxy déclenche le chargement de l'entité réelle à partir de la base de données. Cette approche nécessite d'hériter de votre classe d'entité lors de l'exécution et de remplacer les membres publics, ce qui signifie que ces membres sont virtuels.

Et il existe une autre solution. Vous pouvez ajouter proxy="ISomeInterface" à la déclaration de classe. Ensuite, vous n'avez pas besoin de membres virtuels alors que les proxys implémentent simplement l'interface donnée.

+0

Le modèle de domaine est écrit en VB.NET. Vous ne pouvez pas déclarer les événements comme virtuels (Overridable) dans VB autant que je sache. – Jimit

+0

Je comprends l'exigence pour les membres virtuels, je ne vois pas pourquoi NHibernate aurait besoin que les événements soient virtuels. Les méthodes add_ * et remove_ * d'un événement sont là simplement pour ajouter et supprimer des gestionnaires de l'événement. Ils n'accèdent pas à l'état et donc pas besoin d'être virtuel. – Jimit

+0

J'ai vérifié le code source de NHibernate et il semble que le ProxyTypeValidator.CheckAccessibleMembersAreVirtual (type System.Type, erreurs IList) est l'endroit où l'erreur se produit. La méthode vérifie simplement toutes les méthodes de classe, à l'exception de GetType et vérifie qu'elles sont virtuelles. – Jimit

1

J'ai rencontré le même problème avec l'implémentation de INotifyPropertyChanged sur mes objets chargés paresseux. Le problème est que vous gérez réellement deux instances .NET différentes de sorte que lorsque vous déclenchez l'événement NPC dans votre instance réelle, vous ne le recevez pas à partir de n'importe quelle référence au proxy. Le rendre virtuel permet au proxy de «transmettre» cet événement. Malheureusement, définir des événements comme virtual/overridable n'est pas possible dans VB.NET (2005) et nous avons donc dû introduire un projet C# avec une classe de base implémentant uniquement ces événements virtuels juste pour contourner le problème VB. voir aussi https://forum.hibernate.org/viewtopic.php?f=25&t=990162&start=0

S'il y a d'autres façons que je voudrais connaître moi-même puisque notre méthode rend les procurations un peu moins transparentes qu'elles ne devraient l'être. Aussi dans le domaine de la reconnexion automatique de la session lorsque des objets chargés paresseux doivent être initialisés semblent un peu pénibles.

Cordialement, Theo

Questions connexes