Using AsList() returns null objects depending on the SortOrder

Jason's Avatar

Jason

23 Jul, 2010 02:04 PM via web

In our project, we are using tabs. These tabs have content. Multiple content objects can be on a tab. So we could have a 'car' tab, and that car tab may display a sedan content object, a suv content object and a truck content object. The user could also specify that it contains more or less of these objects and order them however they want. It is important for us to maintain the order of these content objects to user specification.

Here are my mappings :

On the Tab mapping :

        HasManyToMany(t => t.ContentObjects)
            .Table("TabContentObjects")
            .ParentKeyColumn("TabID")
            .ChildKeyColumn("ContentObjectID")
            .AsList(index => index.Column("SortOrder"));

On the ContentObject mapping :

        HasManyToMany(c => c.Tabs)
            .Table("TabContentObjects")
            .ParentKeyColumn("ContentObjectID")
            .ChildKeyColumn("TabID")
            .Cascade.SaveUpdate()
            .AsList(index => index.Column("SortOrder"));

The association table is :

TabContentObjectId
TabId
ContentObjectId
SortOrder  int not null

I am able to add a content object, re-order a content object within a tab, and all is well. nHibernate is adding / updating the SortOrder appropriately. The problem comes when I am trying to delete a content object. When I go to delete the tabs from this contentObject, contentObject.Tabs looks odd.

Here is the code I use to delete the tabs :

                //Need to remove each through the contentObject since it is parent
                foreach (Tab tab in deleteContentObject.Tabs)
                {
                    tab.RemoveContentObject(deleteContentObject);
                }

    //in Tab class
    public virtual void RemoveContentObject(TabContentObject item)
    {
        if (ContentObjects == null) ContentObjects = new List<TabContentObject>();

        ContentObjects.Remove(item);
    }

If it is the ONLY, or the first (SortOrder = 0) contentObject within a tab, I can delete. If it is the second content object, contentObject.Tabs look like [0] [null] [1] [Tab]. If it is the fourth contentObject on the tab, contentObject.Tabs looks like [0] [null] [1] [null] [2] [null] [3][Tab].

So, depending on what the SortOrder column is in the association table, I seem to have many null references returned, and therefore cannot delete due to a null reference. I cannot figure out why these nulls are being returned. Any help would be appreciated.

  1. Support Staff 2 Posted by Paul Batum on 25 Jul, 2010 08:53 AM

    Paul Batum's Avatar

    You might be best off asking for help on the nhibernate
    users<http://groups.google.com/group/nhusers/> mailing
    list as this is really a question that is specifically about NHibernate's
    behavior. If they ask you for an xml version of your mappings, see here:
    http://wiki.fluentnhibernate.org/Fluent_configuration#Exporting_mappings

  2. 3 Posted by jason.sperko on 29 Jul, 2010 09:37 PM

    jason.sperko's Avatar

    Thanks for the info Paul. I guess, in general, is it supported, to map a many-to-many relationship in this fashion?

    Say a Product table, a Order table, and then a ProductOrder table, where the ProductOrder table contains the ProductId, the OrderId, and some SortOrder, where we could sort the Products in any order we wanted to, but have it come back how we sorted.

    Am I correct in saying the mapping would look as it does in my example?

  3. Support Staff 4 Posted by Paul Batum on 30 Jul, 2010 04:46 PM

    Paul Batum's Avatar

    I think its supported but I haven't done it and so I can't really help much.
    This is just the sort of question I'm suggesting you go to the NH list for.
    When it comes to what NH can and cannot do, the list is where the experts
    are.

  4. Support Staff 5 Posted by James Gregory on 31 Jul, 2010 06:40 AM

    James Gregory's Avatar

    I second Paul's suggestion to ask at the NH users list; but from what I've
    used of lists, your situation sounds perfectly normal. When you're using a
    collection with an explicit order (an index, such as a list), NHibernate
    expects the number sequence to be contiguous; if it encounters any gaps in
    the sequence they get filled in with nulls.

    You either need to update the order of items after the one you're deleting
    to compensate for the gap, or not used a strict ordered sequence; instead
    you could just use a bag with an order by.

  5. 6 Posted by jason.sperko on 02 Aug, 2010 05:19 PM

    jason.sperko's Avatar

    I have resolved this with the following :

    Tab Map :

            HasManyToMany(t => t.ContentObjects)
                .Table("wfdc_Tab_TabContentObjects")
                .ParentKeyColumn("TabID")
                .ChildKeyColumn("ContentObjectID")
                .Cascade.SaveUpdate()
                .AsList(index => index.Column("SortOrder"));

    Content Object Map :

            HasManyToMany(c => c.Tabs)
                .Table("wfdc_Tab_TabContentObjects")
                .ParentKeyColumn("ContentObjectID")
                .ChildKeyColumn("TabID")
                .Inverse();

    So I only needed the AsList on one map. I also made the Tab the parent.

    To remove the tabs :

                    foreach (Tab tab in deleteContentObject.Tabs)
                    {
                        tab.ContentObjects.Remove(deleteContentObject);
                    }

    With this configuration, a tab's content is ordered the way we would like. Sorting is automatically updated by nHibernate on updates, add, deletes.

Reply to this discussion

Preview Comments are parsed with Markdown. Help with syntax

Attached Files

    You can attach files up to 10MB

    What is the opposite of north?