-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Intercepting collection changes
PostPosted: Tue Feb 14, 2006 3:20 pm 
Beginner
Beginner

Joined: Wed Oct 05, 2005 2:08 pm
Posts: 23
I love NHibernate, but something has been bugging me. There is no way for a parent to intercept events on a child collection (no SetChanging event on the Iesi Set). As a result, objects can get into invalid states. I thought that the point of having BO's was so that they could ensure that they're state was always valid. Consider the following case:

An Area object has a set of child Zones. Each zone must have a unique number within the Area's collection. A client object adds a Zone object with a number of "3" to an Area's Zone set. The Area's Zone set already contains a Zone with a number of "3". The state of Area is now inconsistent.

How can I avoid this problem? I've tried wrapping the set in my own set with events, which works but it's tricky making sure that all the events are properly attached and detached. Is this the recommended method? Should I be validating this stuff when updating the Area object?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 7:35 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Don't let Area's clients modify Area.Zones directly, but instead create a method like AddZone/RemoveZone and do any checks inside the method. It is possible to map a private property or a field with NHibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 9:28 am 
Beginner
Beginner

Joined: Wed Oct 05, 2005 2:08 pm
Posts: 23
That doesn't strike me as an entirely satisfactory solution as I have to duplicate all the the ISet methods (proceeded by the name of the collection I guess) in the parent object like so:

Customer::AddOrder
Customer::RemoveOrder
Customer::ContainsOrder
Customer::...


Don't misunderstand me, I appreciate the help and this would definitely work, I'm just wondering why this is a better idea than wrapping the ISet with a new Interface IObservableSet which fires events when something is _about_ to be done, allowing any listeners (ideally only the parent object) to throw an exception if something illegal is about to happen. Is there some reason why this would cause problems for Hibernate? Are there any obvious problems with this approach (such as Hibernate not being able to serialize objects)?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 11:53 am 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
All of our collection properties on our entities are publicly exposed as strongly typed. The collecction properties (actually, all of our properties) are mapped with field access, so exposing the actual property with a different type doesn't bother NHibernate (it never accesses the property). These types implement the appropriate .NET collection interface (IList, etc), keep the NHibernate collections internally, expose events such as ItemAdding, ItemAdded, ItemRemoving, ItemRemoved, etc. The collection property's getter lazy-initializes the strongly typed collection (the entity must keep both the stronly and weakly typed collection as separate fields), and passes the owning (parent) entity, item's parent property name, and weakly typed collection-to-wrap to the constructor. The Add/Remove methods automatically set/clear the item's parent property.

This has worked out well so far, since our typical entity has at least 3 or 4 collection properties, and some have over a dozen. It would be ridiculous (and horribly non-OO) to put AddXXX and RemoveXXX methods on the parent entity for every collection property.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 12:18 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
jhusain wrote:
That doesn't strike me as an entirely satisfactory solution as I have to duplicate all the the ISet methods (proceeded by the name of the collection I guess)


Not really, you can use a wrapper class such as ImmutableSet that would prevent anybody from modifying the collection, while still allowing to do other operations. There is a similar wrapper for ILists (call ArrayList.ReadOnly), but I don't know of one for IDictionaries.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.