views:

74

answers:

3

I have a Rotation class, which contains references to multiple lists of Advert objects. I would prefer an implementation where Rotation has a property of type List<List<Advert>> to hold these, but I am unable to come up with an NHibernate mapping supporting this.

In the database schema, the many-to-many relation between Rotation and Advert is represented as a table RotationAdvert with the following columns:

  • RotationID
  • AdvertID
  • Variant ("horizontal position" / index within outer list)
  • Position ("vertical position" / index within inner list)

The best solution I have found yet, is to implement a fixed number of List<Advert> typed properties on Rotation and extend the mapping with a <list> element for each:

<list name="Variant1" table="RotationAdvert" where="Variant = 1">
    <key column="RotationID"/>
    <index column="Position"/>
    <many-to-many class="Advert" column="AdvertID"/>
</list>

<list name="Variant2" table="RotationAdvert" where="Variant = 2">
    <key column="RotationID"/>
    <index column="Position"/>
    <many-to-many class="Advert" column="AdvertID"/>
</list>

etc...

However, this requires me to specify a fixed number of variants, which I really would like to avoid.

What are my other options? Can I squeeze a RotationVariant class into the model - without creating new tables in the database - and somehow map a List<RotationVariant> property on Rotation? Or will I have to create a new table in the database, just to hold an ID for each RotationVariant?

+1  A: 

The best I can think of is to adapt the model to the desired database structure.

class Rotation
{
  IList<AdvertVariant> AdvertVariants { get; private set; }
}


class AdvertVariant
{
  int Variant { get; set; }
  Advert Advert { get; set; }
}

mapping:

<class name="Rotation">
  <list name="AdvertVariants" table="RotationAdvert" >
    <key column="RotationID"/>
    <index column="Position"/>
    <one-to-many class="AdvertVariant"/>
  </list>
</class>

<class name="AdvertVariant">
  <property name="Variant" />
  <many-to-one name="Advert" column="VariantId"/>
</class>

Database:

Rotation:
  id

AdvertVariant
  id
  Variant
  RotationId
  VariantId

Advert
  id

Then you can easily create properties like this:

class Rotation
{
  //...
  IDictionary<int, IList<Adverts>> AdvertsByVariant
  {
    return VariantAdverts.ToDictionary(x => x.Variant, y => y.Advert);
  }
}
Stefan Steinegger
A: 

I'd propose to have a Rotation class which holds a list of Adverts. An advert then holds a list of child adverts in a parent child relationship.

Chris
+1  A: 

I just ran into this same problem today. Reading through the Hibernate documentation and found an answer in section 6.1: Collection Mapping https://www.hibernate.org/hib_docs/nhibernate/html/collections.html:

Collections may not contain other collections

I couldn't find this exact sentence in the NHibernate docs, but it seems that the same rule applies. Like Stephan and Chris said, you will probably need to have another entity to hold the values.

Marc
Thanks for the link, which seems to support the conclusion that I have reached as well. I found a similar statement about NHibernate in one of Ayende's blog posts. In my particular case, I have ended up using a `Dictionary` along with an additional non-persisted property that enables me to do the kind of selection I need. This allows me to keep the database the way it is - no new entities introduced.
Jørn Schou-Rode
Yup, I'm using a non-persisted dictionary to interact with a few of my collections. Seems to work fine for crud updates to the dictionary items too.
Marc