views:

70

answers:

1

I have the following method in my repository. This works fine, my orderItems are initialised as intended however orderItems contains another collection called OrderItemAddress. These are not initialised. How would i do this?

public Model.Order Get(int id)
{
    using (ISession session = NHibernateHelper.OpenSession())
    {
        Model.Order order = session
            .CreateCriteria(typeof(Model.Order))
            .Add(Restrictions.Eq("Id", id))
            .UniqueResult<Model.Order>();

        NHibernateUtil.Initialize(order.OrderItems);
        return order;
    }
}
+3  A: 

First of all you might want to issue only one query to the db server using a join, and not initialize the collection after the order is fetched, like this:

public Model.Order Get(int id)
{
    using (ISession session = NHibernateHelper.OpenSession())
    {
        Model.Order order = session
            .CreateCriteria(typeof(Model.Order))
            .Add(Restrictions.Eq("Id", id))
            .SetFetchMode("OrderItems", FetchMode.Join)
            .UniqueResult<Model.Order>();

        return order;
    }
}

Another thing is to eager load a collection of collections without hurting performance wildly. One way to do that in you scenario is this:

var orderCriteria = DetachedCriteria.For<Order>()
    .SetFetchMode("OrderLines", FetchMode.Eager)
    .Add(Restrictions.Eq("Id", order.Id));

var orderLinesCriteria = DetachedCriteria.For<OrderLine>()
    .CreateAlias("Order", "order")
    .SetFetchMode("Addresses", FetchMode.Eager)
    .Add(Restrictions.Eq("order.Id", order.Id));

IList list = s.CreateMultiCriteria()
    .Add(orderCriteria)
    .Add(orderLinesCriteria)
    .List();

var order = ((IList)list[0]).Cast<Order>().First();

This is unfortunately not tested yet, I am able to do that later. The idea is to make a multiquery that gets all the needed entities in one go (it might not be the most efficient db query possible, but it's at least only one trip) and then let the session stitch up the actual graph from the two result sets.

A slightly different use case is working fine in my current project, but I'm a little unsure if the I have shown here, is completely correct. But I will return on that one :)

EDIT: The above code is changed to something that actually works and is now tested. Sorry for the renaming of the entities and collections. I renamed them slightly for my test project.

asgerhallas
cool thanks, i'll give it a spin.
frosty
I must be tired. Fixed the query to actually do the right thing. And tested.
asgerhallas
Did it work out for you?
asgerhallas
yes! thanks, great work.
frosty