Ok, since no-one is willing to help, I've done more Googling and
discovered that you should map the polymorphic association in the
collection when using the table-per-subclass strategy, and NHibernate
will take care of the rest. So, now I have this:
ProjectMedia - base class, abstract
ProjectVideo - concrete, inherits from ProjectMedia.
ProjectImage - concrete, inherits from ProjectMedia.
Project has a list of Videos, of type ProjectMedia.
Project has a list of Images, of type ProjectMedia.
The project class is as follows:
public class Project
{
// basic properties
public virtual int ProjectId { get; private set; }
... other properties...
public virtual IList<ProjectMedia> Images { get; set; }
public virtual IList<ProjectMedia> Videos { get; set; }
public Project()
{
Images = new List<ProjectMedia>();
Videos = new List<ProjectMedia>();
}
public virtual void AddImage(ProjectImage image)
{
image.Project = this;
Images.Add(image);
}
public virtual void AddVideo(ProjectVideo video)
{
video.Project = this;
Videos.Add(video);
}
}
And the mapping files for all this are:
<class name="Project" table="Projects">
<id name="ProjectId">
<generator class="native" />
</id>
<!-- other properties here -->
<bag name="Images"
cascade="all-delete-orphan"
inverse="true">
<key column="ProjectId" />
<one-to-many class="ProjectMedia" />
</bag>
<bag name="Videos"
cascade="all-delete-orphan"
inverse="true">
<key column="ProjectId" />
<one-to-many class="ProjectMedia" />
</bag>
</class>
And the ProjectMedia mapping as follows:
<class name="ProjectMedia" table="ProjectMedia">
<id name="ProjectMediaId">
<generator class="native" />
</id>
<property name="MediaPath" />
<property name="ThumbnailPath" />
<many-to-one
name="Project"
column="ProjectId"
class="Project" />
<joined-subclass
name="ProjectImage"
table="ProjectImage" lazy="false">
<key column="ProjectMediaId" />
<property name="ImageCredit" />
<property name="ImageCaption" />
</joined-subclass>
<joined-subclass
name="ProjectVideo"
table="ProjectVideo" lazy="false">
<key column="ProjectMediaId" />
<property name="CreditLine" />
</joined-subclass>
</class>
With all of this in place, the saving of the Project with associated
Images and Videos works fine. The problem is, once the Project has
been persisted and then re-loaded, both the collections contain all
the previously-added ProjectImages and ProjectVideos, as opposed to
the Videos collection only containing ProjectVideos and the Images
collection only containing ProjectImages.
Can anyone help with this at all? I'm starting to lose faith in
NHibernate and getting very close to going back to using good old-
fashioned ADO and Stored Procedures for my CRUD operations.
Thanks,
Daniel.
On Jun 23, 12:23 pm, Dan <[email protected]> wrote:
> I'm having trouble with a joined-subclass mapping within my domain
> model using NHibernate.
>
> I have an abstract class "ProjectMedia" with some properties, and 2
> concrete classes that inherit from this class, "ProjectImage" and
> "ProjectVideo". These map to tables ProjectMedia, ProjectImage and
> ProjectVideo, respectively, in the database.
>
> I am using the "Table per subclass" mapping scenario, where the 3
> tables have a shared primary/foreign key so that they can be joined to
> get the concrete data for each object.
>
> Along with this, I have a "Project" class, which has a list of images
> and videos, which map to ProjectImage and ProjectVideo. Here are my
> mappings:
>
> For the Project class:
>
> <class name="Project" table="Projects" lazy="true">
> <id name="ProjectId">
> <generator class="native" />
> </id>
>
> <property name="ProjectDate" not-null="true" />
> ...
> <property name="PDF" not-null="false" />
>
> <bag name="Images" table="ProjectMedia"
> cascade="all-delete-orphan"
> inverse="true">
> <key column="ProjectId" />
> <one-to-many class="ProjectImage" />
> </bag>
>
> <bag name="Videos" table="ProjectMedia"
> cascade="all-delete-orphan"
> inverse="true">
> <key column="ProjectId" />
> <one-to-many class="ProjectVideo" />
> </bag>
> </class>
>
> For the ProjectMedia/ProjectVideo/ProjectImage classes:
>
> <class name="ProjectMedia" table="ProjectMedia" lazy="true">
> <id name="ProjectMediaId">
> <generator class="native" />
> </id>
>
> <property name="MediaPath" />
> <property name="ThumbnailPath" />
>
> <many-to-one name="Project" column="ProjectId"
> class="IdMedia.Data.Domain.Project, IdMedia.Data" not-null="true" />
>
> <joined-subclass
> extends="ProjectMedia"
> name="ProjectImage"
> table="ProjectImage">
> <key column="ProjectImageId" />
> <property name="ImageCredit" />
> <property name="ImageCaption" />
> </joined-subclass>
>
> <joined-subclass
> extends="ProjectMedia"
> name="ProjectVideo"
> table="ProjectVideo">
> <key column="ProjectVideoId" />
> <property name="CreditLine" />
> </joined-subclass>
> </class>
>
> Saving and loading of the project work fine with images and videos
> added to the collection.
>
> However, when I try to access either the Image or Video collections, I
> get this error:
>
> NHibernate.Exceptions.GenericADOException : could not initialize a
> collection: [IdMedia.Data.Domain.Project.Images#163][SQL: SELECT
> images0_.ProjectId as ProjectId1_, images0_.ProjectImageId as
> ProjectI1_1_, images0_.ProjectImageId as ProjectM1_1_0_,
> images0_1_.MediaPath as MediaPath1_0_, images0_1_.ThumbnailPath as
> Thumbnai3_1_0_, images0_1_.ProjectId as ProjectId1_0_,
> images0_.ImageCredit as ImageCre2_2_0_, images0_.ImageCaption as
> ImageCap3_2_0_ FROM ProjectImage images0_ inner join ProjectMedia
> images0_1_ on images0_.ProjectImageId=images0_1_.ProjectMediaId WHERE
> images0_.ProjectId=?]
>
> ----> System.Data.SqlClient.SqlException : Invalid column name
> 'ProjectId'.
> Invalid column name 'ProjectId'.
>
> It seems that NHibernate is setting up the join for the joined-
> subclasses fine, but it has the tables in the join specified in the
> wrong order, therefore, ProjectId (the foreign key to the Projects
> table) is being referenced incorrectly.
>
> Can anyone help with this? I cannot see a reason why this will not
> work the way I have defined the mappings. I have searched everywhere,
> but cannot find an answer. This method was even taken from the book
> "NHibernate in Action", so I cannot understand why it is not working.
>
> I know I can get around it using 1 table per concrete class, but I
> would prefer to do it using joined subclasses, as this saves from data
> repetition.
>
> Thanks,
> Dan.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---