Question

Tried mapping that with FNH and got into a lot of problems, and eventually found out that FNH is lacking, and not maintained anymore, so i decided to try Nhibernate MappingByCode, which works so far but has no documentation...

I can't find how to map IDictionary

        Map(x => x.EntityDict,
            m =>
            {
                m.Key(k => k.Column("ParentID"));
            },
            km =>
            {
                km.//??ManyToMany
            vm =>
            {
                vm.//??ManyToMany
            }
            );

The options in the km(key mapping) are Element (Value type)/ Component (Inner Object in same table)/ ManyToMany (That i don't really understand in this context)

I Tried using ManyToMany in both because it seems the most logical thing, but it didn't work.

When saving the Dictionary SaveUpdate passed, but it didn't save right to the DB, and couldn't Get the Dictionary back.

Edit: here are sample Dictionary structure

public class Entity1Map : ClassMapping<Entity1>
{
    public Entity1Map()
    {
         Id(x=> x.ID,m=>m.Generator(Generators.Guid));
    }
}

public class Entity2Map : ClassMapping<Entity2>
{
    public Entity2Map()
    {
         Id(x=> x.ID,m=>m.Generator(Generators.Guid));
    }
}


public class Entity3 { public IDictionary<Entity1,Entity2> Dict { get;set; } }
public class Entity3Map : ClassMapping<Entity3>
{
    public Entity3Map()
    {
         Id(x=> x.ID,m=>m.Generator(Generators.Guid));

         //Map Dict??
    }
}

as for table structure -

Entity1 Table : ID Column
Entity2 Table : ID Column
Entity3 Table : ID Column
Dict Table : Entity3_ID,Entity1_ID,Entity2_ID

doesn't have to be this table structure if it is saved and recreated from DB in a different one

@Daniel - here is the hbm

<map name="Targets" table="Dict">
  <key column="Entity3ID" />
  <map-key-many-to-many class="Entity1" column="Entity1ID" />
  <many-to-many class="Entity2" column="Entity2ID" />
</map>

Edit 3 (i think) :

        var entity3 = new Entity3();
        var entity1 = new Entity1();
        var entity2= new Entity2();
        entity3.Dict[entity1] = entity2;

        using (var session = GetSession())
        {
            session.SaveOrUpdate(entity1);
            session.SaveOrUpdate(entity2);
            session.SaveOrUpdate(entity3 );
            session.Flush();
        }
Was it helpful?

Solution

NHibernate Collections

Every NHibernate collection (bag, set, map, list, etc.) has a key and something describing the contents of the collection. A couple collection types, list and map, also have something that describes the index of the collection.

key is the foreign key that points back to the entity that owns the collection.

The contents of the collection will be described by one of the following elements:

  • one-to-many: the contents of the collection are some kind of entity, and the table for that entity is used as the table for the collection. This implies that the other entity probably has a many-to-one relationship back to this one. Whether you actually end up including that relationship in your object model is a different matter.
  • many-to-many: the contents of the collection are an entity, but an intermediate table is used for the collection so that the collection elements can be reused by other collections.
  • element: the contents of the collection are some kind of simple value type, like int, string, etc. A table should be specified for the collection since these value types don't have any particular table they normally live in.
  • composite-element: Similar to element, but here multiple columns are mapped to properties in a component class.

Finally, for the index, your choices are either:

  • index: the index is a simple value type, like int or string. This is the only type of index available for lists. On a list, these values correspond directly to the list's index values, list[0], list[1], etc., so non-sequential values in this column will result in some null values in the .NET collection. index has been renamed to list-index and map-key for lists and maps respectively. Both the old and new names should work.
  • index-many-to-many: the index is an entity. index-many-to-many has been renamed to map-key-many-to-many. The old and new names both work.

There may be a few more options available, but these are the most commonly used ones.

Your Dictionary

In your case, Entity3 has a dictionary of Entity2s, indexed by Entity1, and separate tables are used to keep track of Entity2 and this collection. This means we need a map with a map-key-many-to-many (because the index is an entity) and a many-to-many (because the contents are an entity but we're using a separate table). In HBM XML this would look like:

<map name="Dict" table="Dict">
    <key column="Entity3_ID" />
    <map-key-many-to-many class="Entity1" column="Entity1_ID" />
    <many-to-many class="Entity2" column="Entity2_ID" />
</map>

You do this in FluentNHibernate with the AsEntityMap method:

HasManyToMany(x => x.Dict)
    .Table("Dict")
    .ParentKeyColumn("Entity3_ID")
    .AsEntityMap("Entity1_ID", "Entity2_ID");

With mapping by code, I would imagine that something like this...

Map(x => x.Dict,
    c =>
    {
        c.Table("Dict");
        c.Key(k => k.Column("Entity3_ID"));
    },
    i => i.ManyToMany(m => m.Column("Entity1_ID")),
    v => v.ManyToMany(m => m.Column("Entity2_ID")));

... would do the trick.

I haven't tested the above mappings, and this is my first attempt at mapping by code, so let me know whether it works or not.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top