R – Many-to-many collection mapping in NHibernate

nhibernatenhibernate-mapping

My application is a multi-user podcast aggregator, using NHibernate 2.1 (and .NET 4.0 if that changes anything). I'm also a complete NHibernate n00b.

Details of each podcast are only stored once, and Users subscribe to podcasts, so there is a many-to-many mapping between podcasts and users which I have mapped in my database with a Subscriptions table:

Subscriptions(UserId, FeedId)

I also have a UserFeedItems table which stores per-user-per-item information:

UserFeedItems(UserId, FeedItemId, IsNew, ListenCount, etc.)

My object model is a bit different:

class Podcast {
    IList<PodcastFeedItem> FeedItems { get; set; }
    bool HasNew {
        get {
            // return true if any of the FeedItems are new
        }
    }
}

class PodcastFeedItem {
    bool IsNew { get; set; }
}

class User {
    IList<PodcastFeed> Subscriptions { get; set; }
}

What mappings do I need in NHibernate to correctly map the relational model to the object model? Have I gone to far by defining those "link" tables listed above? Ordering may be important here, as obviously I need to keep the feeds organised in descending chronological order.

I've read through the documentation on collection mapping, but I'm struggling to fit the examples to my own scenario.

Best Answer

Its a classic Many-to-Many where a Podcast can have many subscribers and a subscriber can subscribe to many podcasts. You map it like this:

<class name="App.Core.Domain.User, App.Core" table="users">
    <set name="SubscribedPodcasts" table="subscriptions" inverse="false" cascade="all">
      <key column="userid"/>
      <many-to-many class="App.Core.Domain.Podcasts, App.Core" column="podcastid"/>
    </set>
</class>


<class name="App.Core.Domain.Podcast, App.Core" table="podcasts">
    <set name="SubscribedUsers" table="subscriptions" inverse="false" cascade="all">
      <key column="podcastid"/>
      <many-to-many class="App.Core.Domain.User, App.Core" column="userid"/>
    </set>
</class>

If you really want to store the index in the database rather than having NH order the results (I have never had to do this as its better to order by a column and have NH provide your indexes). then add

<index-many-to-many
        column="column_name"                
        class="ClassName"                   
/>

To the mapping

Related Topic