How to map an IDictionary<String, CustomCollectionType> in NHibernate
- by devonlazarus
Very close to what I'm trying to do but not quite the answer I think I'm looking for:
How to map IDictionary<string, Entity> in Fluent NHibernate
I'm trying to implement an IDictionary<String, IList<MyEntity>>and map this collection to the database using NHibernate. I do understand that you cannot map collections of collections directly in NHibernate, but I do need the functionality of accessing an ordered list of elements by key.
I've implemented IUserCollectionType for my IList<MyEntity> so that I can use IDictionary<String, MyCustomCollectionType> but am struggling with how to get the map to work as I'd like.
Details
This is the database I'm trying to model:
------------------------
-------------------- | EntityAttributes |
| Entities | ------------------------ ------------------
-------------------- | EntityAttributeId PK | | Attributes |
| EntityId PK | <- | EntityId FK | ------------------
| DateCreated | | AttributeId FK | -> | AttributeId PK |
-------------------- | AttributeValue | | AttributeName |
------------------------ ------------------
Here are my domain classes:
public class Entity
{
public virtual Int32 Id { get; private set; }
public virtual DateTime DateCreated { get; private set; }
...
}
public class EavEntity : Entity
{
public virtual IDictionary<String, EavEntityAttributeList> Attributes
{
get;
protected set;
}
...
}
public class EavAttribute : Entity
{
public virtual String Name { get; set; }
...
}
public class EavEntityAttribute : Entity
{
public virtual EavEntity EavEntity { get; private set; }
public virtual EavAttribute EavAttribute { get; private set; }
public virtual Object AttributeValue { get; set; }
...
}
public class EavEntityAttributeList : List<EavEntityAttribute>
{
}
I've also implemented the NH-specific custom collection classes IUserCollectionType and PersistentList
And here is my mapping so far:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" ...>
<class xmlns="urn:nhibernate-mapping-2.2" name="EavEntity" table="Entities">
<id name="Id" type="System.Int32">
<column name="EntityId" />
<generator class="identity" />
</id>
...
<map
cascade="all-delete-orphan"
collection-type="EavEntityAttributeListType"
name="EntityAttributes">
<key>
<column name="EntityId" />
</key>
<index type="System.String">
<column name="Name" />
</index>
<one-to-many class="EavEntityAttributeList" />
</map>
</class>
</hibernate-mapping>
I know the <map> tag is partially correct, but I'm not sure how to get NH to utilize my IUserCollectionType to persist the model to the database.
What I'd like to see (and this isn't right, I know) is something like:
<map
cascade="all-delete-orphan"
collection-type="EavEntityAttributeListType"
name="EntityAttributes">
<key>
<column name="EntityId" />
</key>
<index type="System.String">
<column name="Name" />
</index>
<list>
<index column="DisplayOrder">
<one-to-many class="EntityAttributes">
</list>
</map>
Does anyone have any suggestions on how to properly map that IDictionary<String, EavEntityAttributeList> collection?
I am using Fluent NH so I'll take examples using that library, but I'm hand mappings are just as helpful here.