views:

66

answers:

2

Hi!

Here are my relevant classes:

public class ArticleMetadata
{
    public long ID { get; set; }

    public string Slug { get; set; }
}

public class Article : ArticleMetadata
{
    // This is a massive CLOB, hence separate class
    public string Content { get; set; }
}

public class Section
{
    public long ID { get; set; }

    public IList<ArticleMetadata> Articles { get; set; }
}

And here are relevant mapping parts:

<class name="Article" table="Article">
</class>

<!-- Note that there's no explicit NHibernate inheritance mapping here -->
<class name="ArticleMetadata" table="Article">
</class>

<class name="Section" table="Section">  
    <bag name="Articles" cascade="all-delete-orphan" inverse="true" lazy="false">
        <key column="SectionID" />
        <one-to-many class="ArticleMetadata" />
    </bag>
</class>

Hope it's all clear up until now.

What I'm trying to do is as follows: when selecting my Section objects, I want them to contain only "lightweight" ArticleMetadata objects. But when saving Section to the DB, I want NHibernate to persist Article objects as well:

var section = new Section();
section.Articles.Add(new ArticleMetadata("a1"));
section.Articles.Add(new Article("a2", "massive clob"));

session.SaveOrUpdate(section);

Currently, SaveOrUpdate exit without any errors whatsoever, but a full-blown Article object gets saved only partially. That is, value of its' Content property never makes it to the DB.

Saving Article separately (session.Save(new Article(...));) works as expected, saving all mapped properties.

To sum it up: I want to add both ArticleMetadata and Article objects to Section.Articles collection, and want them to be saved appropriately. Is this kind of behavior possible at all?

+3  A: 

I know it isn't a direct solution to your problem (I don't think what you're doing can work without the inheritance mapping, and then you have the clob loaded too).

One way to do what it seems that you want, is to make Content a lazy loaded property, and drop the inheritance.

More on lazy loaded properties can be found here: http://ayende.com/Blog/archive/2010/01/27/nhibernate-new-feature-lazy-properties.aspx

Another way is to have two collections, one for Articles and one for ArticleMetadata.

asgerhallas
A: 

I think you will need to persist Article-objects explicitly in order to get them to work. I assume the Section-cascade treats them as ArticleMetadata and hence, store them as such.

Otherwise, if you don't specify cascading, and use session.Create(new Article()) on them instead, then maybe the flush mechanism would take care of it for you. Cascading is only useful if you don't explicitly create the objects afaik.

One pointer though. In order to NOT load a fully blown Article when you select ArticleMetadata, you must specify polymorphism="explicit" on your class-mapping on ArticleMetadata, otherwise it will identify the inheritance and select your Article on a separate query every time.

jishi