tags:

views:

941

answers:

4

I'm trying filter the child collection of an aggregate root when loading it with Nhibernate. Load a Customer with all their Orders that have been shipped. Is this possible?

+1  A: 

Well, you can expose properties that are filtered in the map, like so:

<bag name="shippedOrders" ... where="Status == 'Shipped'" >
   <key column="CustomerId" />
   <one-to-many class="Order" />
</bag>

The 'where' attribute is arbitrary SQL.

Theoretically you could have two properties of Customer, Orders and ShippedOrders. However, I should say that I have not done this, and I would want to test how NH handles cascading in this case. In any case, you will have to take care when new items are added/removed that they are added/removed correctly to both collections.

The fact that you want to do this makes we wonder if Order is an aggregate root. It might be less trouble in the long run doing it like this:

orderRepository.GetOrders(int customerId, OrderStatus[] statuses)
Tim Scott
This would involve loading the Orders twice though - even though there'd only be distinct entities for them
David Kemp
+1  A: 

You could look at it the other way - load all the shipped orders for a Customer.

session.CreateCriteria( typeOf(Order) )
    .Add( Restrictions.Eq("Shipped", shippedStatus ) )
    .Add( Restrictions.Eq("Customer", requiredCustomer) )
    .List<Order>();
David Kemp
+1  A: 

You can also do it using HQL using session.Filter(customer.Orders, "where this.Status == 'Shipped'");

Sebastian Markbåge
+1  A: 
ICriteria crit = session.CreateCriteria (typeof(Customer));

crit.CreateAlias ("Orders", "o");
crit.Add (Expression.Eq ("o.Status", shippedStatus));
crit.Add (Expression.Eq ("Id", customerId));

return crit.UniqueResult <Customer>();

something like that.

Frederik Gheysels