tags:

views:

74

answers:

1

I've always taken a data centric approach to web apps, and so the paradigm change involved when taking a pure OO approach using ORMs is still not completely natural to me, and evey now and then something ostensibly simple is not obvious.

Can someone please point me into the right direction of how to correctly model this situation in an ORM (Specifically NHibernate).

The situation: There are many Users, Many Items, users may rate Items.

In a data centric/relational approach it would look like this (and be very easy!):

- Items Table
ItemID 
ItemName

- UserRatings Table
UserID 
ItemID 
Rating

- Users Table
UserID 
UserName

If you want to find out what rating your logged in user gave for a particular item, you just do a joined query.

However, it's not obvious to me how to model this in a OO way when using an ORM. I beleive I need three domain classes: Item, UserRating, and User. Presumably I also need a collection of UserRatings in the Items class, and a collection of UserRatings in the User class. But how do I navigate to the corect UserRating, from a particular item which I have loaded (and of course this UserRating must be the one related to the user I'm interested in).

Can anyone clarify this for me?

Thanks

+2  A: 

Your classes would look like the following

public class User 
{
    public virtual int UserId { get; set; }
    public virtual string UserName { get; set; }
    public virtual IList<UserRating> Ratings { get; set; }
}

public class Item 
{
    public virtual int ItemId { get; set; }
    public virtual string ItemName { get; set; }
    public virtual IList<UserRating> Ratings { get; set; }
}
public class UserRating 
{
    public virtual User User { get; set; }
    public virtual Item Item { get; set; }
    public virtual Int32 Rating { get; set; }
}

Your mapping file would look like

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Test" namespace="Test" >
    <class name="User">
     <id name="UserId" >
      <generator class="native" />
     </id>
     <property name="UserName" />
     <bag name="Ratings" generic="true" inverse="true" table="UserRating">
      <key column="UserId" />
      <one-to-many class="UserRating"/>
     </bag>
    </class>
    <class name="Item" >
     <id name="ItemId" >
      <generator class="native" />
     </id>
     <property name="ItemName" />
     <bag name="Ratings" generic="true" inverse="true" table="UserRating">
      <key column="ItemId" />
      <one-to-many class="UserRating"/>
     </bag>
    </class>
    <class name="UserRating" >
     <composite-id>
      <key-many-to-one class="User" column="UserId" name="User" />
      <key-many-to-one class="Item" column="ItemId" name="Item" />
     </composite-id>
     <property name="Rating" />
    </class>
</hibernate-mapping>

I would suggest you look at the Summer of Nhibernate screen cast as well as the Autumn of Agile series by Stephen Bohlen which gave me a great start with nhibernate.

Nathan Fisher
Do you know a site taht streams those videos? The offial site doesn't seem to.
UpTheCreek
No I don't but you can just download them and watch them
Nathan Fisher
For the first few screen casts (6 ithink) you will need to install the Techsmith Camtasia Codecs, after that they are media player friendly.
Nathan Fisher
I wouldn't setup bidirectional relationships (between User and UserRating and between Item and UserRating) unless I knew for a fact that they were needed in the application. It would be simpler and more efficient to only map one end of each relationship.
John Rayner