2009-03-20 9 views
1

Je n'arrive pas à configurer une structure basée sur les rôles en utilisant l'héritage et NHibernate.Héritage de table unique NHibernate

Fondamentalement, je voudrais avoir une classe abstraite appelée ObjectInRole. Cette classe (et la table de base de données correspondante) contient un RoleId, un ObjectId et un ObjectType (ce serait la colonne discriminante). La colonne discriminante est le type d'objet qui gagne le rôle. Pour des raisons de simplicité, supposons qu'il existe un objet Utilisateur qui contient une liste (sac) de Rôles. Je voudrais que je puisse avoir une classe UserInRole qui serait une sous-classe de ObjectInRole.

J'ai créé ce sac comme ceci:

<bag name="Roles" table="ObjectInRole" where="ObjectType = 'AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core'" generic="true" 
    access="field.pascalcase-underscore" lazy="true"> 
    <key column="ObjectId" /> 
    <many-to-many class="AthletesCafe.Core.Domain.System.Roles.Role, AthletesCafe.Core" column="RoleId" /> 
</bag> 

J'ai mis en place le mappage pour le ObjectInRole être ceci:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="AthletesCafe.Core.Domain.System.Roles" assembly="AthletesCafe.Core"> 
    <class name="ObjectInRole" table="ObjectInRole" lazy="true" abstract="true"> 
<id name="ID" type="Int32" unsaved-value="0"> 
    <column name="ID" not-null="true" unique="true" index="PK_ObjectInRole"/> 
    <generator class="identity" /> 
</id> 
<discriminator column="ObjectType" type="String" insert="true" force="true"/> 
<property name="ApplicationName" column="ApplicationName" type="String" not-null="false" length="255" /> 
<property name="ObjectId" column="ObjectId" type="int" not-null="true" /> 
<property name="ObjectType" column="ObjectType" type="String" /> 

<many-to-one name="Role" column="RoleId" class="AthletesCafe.Core.Domain.System.Roles.Role, AthletesCafe.Core" not-null="true" cascade="none" /> 

<subclass name="AthletesCafe.Core.Domain.System.Roles.UserInRole" 
      discriminator-value="AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core"> 
    <many-to-one name="User" column="ObjectId" class="AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core" not-null="false" cascade="none" /> 
</subclass> 

Ayant cette configuration et en cours d'exécution je ne peux pas obtenir le champ ObjectType à enregistrer lorsque j'ajoute un nouveau rôle à la collection pour l'objet Utilisateur. Il enregistre une nouvelle entrée dans la table ObjectToRole, mais le ObjectType est null. En regardant le sac, il ne serait pas charger dans la collection. Je pense que je l'ai réduit à la structure de la sous-classe en cours d'installation incorrecte ou que le sac est mal configuré. Je penche pour le sac car je pense qu'il peut juste traiter la collection comme un bouquet de la classe abstraite au lieu de la sous-classe UserInRole.

Veuillez donner votre avis sur les deux domaines. Merci!

EDIT:

Ainsi, au lieu d'essayer d'ajouter au sac (User.Roles.add (rôle)) et ayant le nombre à plusieurs objets Conserve le liant j'ai décidé que j'ajouter tout droit de la objet à la table. Je reçois une nouvelle erreur:

null id in AthletesCafe.Core.Domain.System.Roles.UserInRole entry (don't flush the Session after an exception occurs) 

Si vous regardez la classe ci-dessus, j'ai défini l'objet Utilisateur et l'objet Rôle. L'identifiant est un champ d'identité et est spécifié comme tel. Je suis complètement perdu.

Répondre

2

OK! Après avoir beaucoup joué avec les fichiers de cartographie, j'ai trouvé un problème non documenté (au moins, je ne pouvais trouver aucune mention de l'erreur que je commettais).

Lors de l'utilisation de sous-classes, la classe parente ne peut pas contenir un mappage pour une propriété qui est la colonne discriminante. Si vous regardez le deuxième document de cartographie que j'ai posté, il montre la super classe et la sous-classe. Le discriminateur de la super classe est la colonne ObjectType. Je mappe également cela en tant que propriété à la classe abstraite ObjectInRole. Tu ne peux pas faire ça. Une fois cette ligne enlevée, tout fonctionnait correctement (pas de sauvegarde du sac).

Le sac semble être un problème qui n'est pas contrôlable par tout ce que j'ai trouvé dans la documentation. Je ne peux pas trouver une autre instance de l'endroit où la classe abstraite est enregistrée grâce à la cartographie. Il semble que NHibernate ne sache pas que la classe de liaison est un objet UserInRole et non un objet ObjectInRole. En recherchant toutes les options qui sont fournies pour le nœud du sac, il n'y avait pas de façon apparente de dire à NHibernate le type de classe auquel il était lié pour faire l'association plusieurs-à-plusieurs. De ce que je peux dire, cela ne fait rien, mais traite plus ou moins la table comme une simple table, pas un objet mappé. S'il y avait un moyen de le dire ajouter quelque chose pour l'insertion alors peut-être que ce serait possible, mais je n'ai vu aucune information à ce sujet.

Questions connexes