2009-03-20 14 views
1

Ich habe Probleme beim Einrichten einer rollenbasierten Struktur mit Vererbung und NHibernate.NHibernate Single Table Inheritance

Grundsätzlich möchte ich eine abstrakte Klasse namens ObjectInRole haben. Diese Klasse (und die entsprechende Datenbanktabelle) enthält eine RoleId, eine ObjectId und einen ObjectType (dies wäre die Diskriminatorspalte). Die Diskriminatorspalte wäre der Objekttyp, der die Rolle erhält.

Der Einfachheit halber wird angenommen, dass es ein Benutzerobjekt gibt, das eine Liste (Tasche) von Rollen enthält. Ich möchte es so, dass ich eine UserInRole-Klasse haben kann, die eine Unterklasse von ObjectInRole wäre.

ich diese Tasche wie diese erstellt haben:

<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> 

ich die Zuordnung eingerichtet haben für die ObjectInRole dies sein:

<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> 

dieses Setup zu haben und Ich kann das ObjectType-Feld nicht speichern, wenn ich der Sammlung für das User-Objekt eine neue Rolle hinzufüge. Es speichert einen neuen Eintrag in der ObjectToRole-Tabelle, aber der ObjectType ist null. Betrachtet man die Tasche, würde sie diese nicht in die Sammlung laden. Ich glaube, ich habe mich darauf beschränkt, dass die Unterklassenstruktur falsch eingerichtet wird oder dass die Tasche falsch eingerichtet ist. Ich lehne mich der Tasche zu, da ich denke, dass es die Sammlung nur als ein Bündel der abstrakten Klasse anstatt der Unterklasse UserInRole behandelt.

Bitte geben Sie Ihre Gedanken zu beiden Bereichen. Vielen Dank!

EDIT:

Also anstatt zu versuchen, um die Tasche (User.Roles.add (Rolle)) und mit dem many-to-many bleibt das Verknüpfungsobjekt entschied ich mich hinzufügen, dass ich nur gerade die hinzufügen Objekt an den Tisch. Ich erhalte einen neuen Fehler:

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

Wenn in der Klasse der Suche oben ich das Benutzerobjekt und Role-Objekt festgelegt haben. Die ID ist ein Identitätsfeld und wird als solches angegeben. Ich bin völlig am Ende.

Antwort

2

OK! Nachdem ich viel mit Mapping-Dateien herumgespielt habe, habe ich ein undokumentiertes Problem gefunden (zumindest konnte ich den Fehler, den ich beging, nicht erwähnen).

Bei der Verwendung von Unterklassen kann die Elternklasse keine Zuordnung für eine Eigenschaft enthalten, bei der es sich um die Diskriminatorspalte handelt. Wenn Sie sich das zweite Mapping-Dokument ansehen, das ich gepostet habe, werden die Super-Klasse und die Sub-Klasse angezeigt. Der Diskriminator der Superklasse ist die ObjectType-Spalte. Ich ordne das auch als eine Eigenschaft der abstrakten Klasse ObjectInRole zu. Du kannst das nicht machen. Sobald diese Linie entfernt wurde, funktionierte alles richtig (nicht die Tasche zu speichern).

Die Tasche scheint ein Problem zu sein, das durch nichts, was ich in der Dokumentation gefunden habe, kontrollierbar ist. Ich kann keine andere Instanz finden, in der die abstrakte Klasse durch das Mapping gespeichert wird. Es scheint, dass NHibernate nicht weiß, dass die Verknüpfungsklasse ein UserInRole-Objekt und kein ObjectInRole-Objekt ist. Bei der Untersuchung aller Optionen, die für den bag-Knoten zur Verfügung gestellt werden, gab es keine offensichtliche Möglichkeit, NHibernate mitzuteilen, mit welchem ​​Typ von Klasse es gelinkt hat, die Viele-zu-Viele-Verknüpfung herzustellen. Von dem, was ich sagen kann, ist es egal, aber mehr oder weniger behandelt die Tabelle als nur eine Tabelle, kein zugeordnetes Objekt. Wenn es eine Möglichkeit gäbe, es etwas für die Beilage anzuhängen, wäre es vielleicht möglich, aber ich habe diesbezüglich keine Informationen gesehen.

Verwandte Themen