Reconsituting Domain Collections with NHibernate

We ran into a problem using NHibernate to persist our domain. Here's an example of a domain object; an Order class with a collection of OrderLine objects to represent the line in each order placed in the system. In the system we want to be able to check if an order exists or not so we use an anonymous delegate as a predicate on the OrderLine collection:

    7 class Order

    8 {

    9     private IList<OrderLine> Lines;

   10 

   11     public Order()

   12     {

   13         Lines = new List<OrderLine>();

   14     }

   15 

   16     public bool DoesOrderExist(string OrderNumber)

   17     {

   18         return ((List<OrderLine>)Lines).Exists(

   19             delegate(OrderLine line)

   20                 {

   21                     if (line.OrderNumber == OrderNumber)

   22                         return true;

   23                     return false;

   24                 }

   25             );

   26     }

   27 }

   28 

   29 class OrderLine

   30 {

   31     public string OrderNumber;

   32     public int Quantity;

   33     public string Item;

   34     public double Cost;

   35 }

This is all fine and dandy but when we reconsistute the object from the back-end data store using NHibernate, it blows its head off with an exception saying it can't cast the collection to a list. Internally NHibernate creates a PersistantBag object (which implements IList) but can't be directly cast to a List, so we can't use our predicate.

There's a quick fix we came up with which is to modify the DoesOrderExist method to look like this instead:

   16 public bool DoesOrderExist(string OrderNumber)

   17 {

   18     List<OrderLine> list = new List<OrderLine>(Lines);

   19     return (list.Exists(

   20         delegate(OrderLine line)

   21             {

   22                 if (line.OrderNumber == OrderNumber)

   23                     return true;

   24                 return false;

   25             }

   26         );

   27 }

This feel dirty and smells like a hack to me. Rebuilding the list from the original one when we want to find something? Sure, we could do this and cache it (so we're not recreating it every time) but that just seems ugly.

Any other ideas about how to keep our predicates intact when reconsituting collections?

Published Tuesday, May 01, 2007 10:14 AM by Bil Simser
Filed under: ,

Comments

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 1:19 PM by FransBouma

Ain't POCO fun :)

I really wonder why you don't use a simple for loop, as it's less lines and better readable and has at least the same performance.

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 1:34 PM by Bil Simser

I suppose you could collapse the predicate to delegate(OrderLine line) { return line.OrderNumber == OrderNumber; } or delegate(OrderLine line) { return line.OrderNumber.CompareTo(OrderNumber); } which would cut down on the code but yeah, a simple for loop would work here.

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 2:29 PM by FransBouma

Another possibility is to re-introduce repositories, as these kind of methods should perhaps be in a repository instead of the domain object / aggregate.

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 2:40 PM by Bil Simser

Should they? In this case we're talking about something theoretical, but in a real domain it would have a set of objects that are really part of it (in our case we have a cable with segments).

It doesn't seem to make sense to create an entire repository just to hand out segments from a list when they're really part of the Cable.

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 4:09 PM by Udi Dahan - The Software Simplist

I feel your pain. In this specific scenario, I'm with Frans - just "foreach" it.

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 4:51 PM by Ayende Rahien

A for / foreach would be better here.

Another option is to use a helper method that accept a collection and a delegate, and calls the delegate on each item.

# re: Reconsituting Domain Collections with NHibernate

Tuesday, May 01, 2007 10:59 PM by Jeff Perrin

I'll recommend the foreach as well. Anonymous delegates are great for readability and conciseness (is that a word?)... if the syntax is good. Unfortunately in 2.0 it's just ugly. You could also wrap up the anonymous delegate as a Specification object if you want to test it separately. Then you could call list.Exists(spec.IsSatisfiedBy).

# re: Reconsituting Domain Collections with NHibernate

Wednesday, May 02, 2007 4:48 AM by Aaron

Just taking a different route for the sake of it (I don't actually think doing that cast is a 'Good Thing' anyway), but...

Can't you make NHibernate map that association using a List ? Perhaps involves explicitly avoiding lazy loading ?

Leave a Comment

(required) 
(required) 
(optional)
(required)