Problema con NHibernate e Table for Hierarchy
Posted by imperugo in Nhibernate on Monday 18 May 2009 at 3:55 AM
Tempo fa, insieme a Marco, mi sono imbattuto in un problema relativo al fetching di collection polimorfiche tramite NHibernate.
In pratica, quando si hanno collection il cui tipo contenuto eredita da un’altra entity persistita tramite Table for Hierarchy (maggiori info qui) , si possono riscontrare dei problemi in fase di fetching quando la collection è contenuta in una entity parent.
Per capire meglio il significato di quanto appena detto si osservi il diagramma di classe seguente:
Per la situazione sopra descritta si avrà un mapping come il seguente:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
schema="dbo"
xmlns="urn:nhibernate-mapping-2.2"
default-access="property"
namespace="ConsoleApplication1.ObjectModel"
assembly="ConsoleApplication1">
<class name="Post" table="Posts" lazy="true" dynamic-update="true">
<id name="ID" column="ID" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="Title">
<column name="Title" sql-type="nvarchar(100)" not-null="true" />
</property>
<bag name="PostTags" cascade="all-delete-orphan" generic="true">
<key column="PostID" />
<one-to-many class="PostTag" />
</bag>
<bag name="ImageTags" cascade="all-delete-orphan" generic="true">
<key column="PostID" />
<one-to-many class="ImageTag" />
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
schema="dbo"
xmlns="urn:nhibernate-mapping-2.2"
default-access="property"
namespace="ConsoleApplication1.ObjectModel"
assembly="ConsoleApplication1">
<class name="TagBase" table="Tags" lazy="true" dynamic-update="true">
<id name="ID" column="ID" unsaved-value="0">
<generator class="identity"/>
</id>
<discriminator force="true">
<column name="Discriminator" not-null="true" sql-type="int" />
</discriminator>
<property name="Name">
<column name="Name" sql-type="nvarchar(100)" not-null="true" />
</property>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
schema="dbo"
xmlns="urn:nhibernate-mapping-2.2"
default-access="property"
namespace="ConsoleApplication1.ObjectModel"
assembly="ConsoleApplication1">
<subclass name="ImageTag" extends="TagBase" discriminator-value="1" >
</subclass>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
schema="dbo"
xmlns="urn:nhibernate-mapping-2.2"
default-access="property"
namespace="ConsoleApplication1.ObjectModel"
assembly="ConsoleApplication1">
<subclass name="PostTag" extends="TagBase" discriminator-value="0">
</subclass>
</hibernate-mapping>
Se si tenta di recuperare una collection di PostTag non si riscontrano problemi; al contrario, se si tenta di recuperare un’istanza della classe Post e, allo stesso tempo, la collection PostTag ad esso associata, si andrà incontro ad un’eccezione.
Per ovviare al problema basta inserire nel mapping della collection la where con il discriminator, come mostrato di seguito:
<bag name="PostTags" cascade="all-delete-orphan" generic="true" where="Discriminator = 0">
<key column="PostID" />
<one-to-many class="PostTag" />
</bag>
<bag name="ImageTags" cascade="all-delete-orphan" generic="true" where="Discriminator = 1">
<key column="PostID" />
<one-to-many class="ImageTag" />
</bag>
Questo comportamento, pur essendo documentato dal team di Nhibernate qui, resta comunque strano.
Un’altra soluzione, sicuramente più comoda e mantenibile, consiste nell’impostare l’attributo force del discriminator a true, dicendo così ad Nhibernate di specificare sempre la where del discriminator nelle proprie query, come mostrato dal seguente mapping:
<discriminator force="true"> <column name="Discriminator" not-null="true" sql-type="int" /> </discriminator>
In allegato potete trovare un esempio che riproduce il problema.
Maggiori informazioni ed aggiornamenti potete trovarli qui.
Download Esempio qui
The comments for this post are closed.
- There is no TrackBack for this post.
Archive