Design Question

Design Question

Old forum URL: forums.lhotka.net/forums/t/2781.aspx


hatem_info posted on Thursday, April 26, 2007

I have the situation where my child collection must be persisted ­(DB) and keep the exact order of lines items (after an insert or an update). I can insert a line item between 2 other items.

 My question is how I can do this with CSLA?

ajj3085 replied on Thursday, April 26, 2007

You need to keep track of the ordering of items.  I do this with line items in my application.

The underling collection is a list, which always keeps items in the same order.  When saving, you need to save the index in the list to the db.  Then when you load, you need to order the items by that position.

HTH

RockfordLhotka replied on Thursday, April 26, 2007

You may need to add an "OrderPosition" property to your child class, and use that to maintain the order. Even if that value isn't saved to the db, you can use it to keep the order consistent in your list.

The primary reasons are these:

  1. If you allow the user to insert items in the middle, you need a way to manage that
  2. If you allow the user to move items in the list, you need a way to track positions
  3. If you allow the user to delete items in the list, and you support a "cancel" operation, BusinessListBase will not maintain the original ordering of the items, and you need a way to reconcile the ordering

This OrderPosition (numeric, ascending value) property gives you a tool to manage the positions of the items.

Q Johnson replied on Thursday, April 26, 2007

I did this for one of my own applications and the key for me was deciding that the index maintenance for the children was the responsibility of the collection class of which they are all members.

There are really three considerations it seems: index value maintenance while the collection is in use, persistance of the collection, and UI stuff.

Index Maintenance: Once I decided to make it the collection's responsibility, the implementation seemed pretty straightforward.  I didn't support insertion as you describe it here, but that isn't a big leap, really.  I think a Public method for the collection can still handle it all - something like InsertAt() which would take an argument to trigger the correct index management behavior.  InsertAt() calls the .Add() method, and then branches based on whether the argument was less than .Count (or .Count -1, depending on whether your index is going to be one-based or zero-based).  If the new one is the last item (not inserted; just added) the index is simply set to the next value (new .Count or .Count -1).  If it is being inserted, the code will assign the new/last item a value larger than the highest value (or -1 or some other convenient and impossible value), re-order all the existing items whose index is equal to or greater than the desired value for the new guy, and then assign the desired value to the new one.

Persistence: In my own case, I chose to simply delete all the children from the DB and re-save them as new ones every time.  My collections were rarely more than a dozen items, so such a choice was easy for me.  If you think yours might involve a few thousand, you may have to question this.

UI: I can't offer any guidance here because it varies so much depending on how the user interacts with your collection members.  But as long as the UI can generate the call to InsertAt() appropriately per the above design, it shouldn't be too great a challenge.  If it can't, you can take that into consideration in designing a more appropriate InsertAt() argument list that the UI can populate.

I hope this is enough to get you started down the right road.

 

hatem_info replied on Thursday, April 26, 2007

I think that the index Maintenance is the most suited for me:

  1/ Let the responsibility to the BO to maintain the order of line items

  2/ delete all the children from the DB and re-save the new ones is not always 
      possible (take the case where it’s not possible to delete one line item according to 
      business logic constraint (DB Trigger))

  3/ UI is not the best place for such responsibility.

Q Johnson replied on Thursday, April 26, 2007

I'm sorry if I wasn't clear in the first posting.  All three of these issues need to be addressed by your solution.  I wasn't trying to offer them as a list of choices from which you select only one.

Clearly you do need to maintain the indexes.  Although I didn't specify it, I was assuming the Child Objects have the index number property that Rocky mentions in his post.  I can't imagine a solution without that property available.  You certainly don't have to show it in the UI, though.

You must have some method of persistence of the children.  I simply offered my own solution. If you don't like my "mass delete/re-save" technique, you can still get the update process to work properly as long as each of your Child objects has a unique ID (obviously NOT the sorting index value that is our focus here).  Many developers use unique IDs for all their tables and, so, one would be available for child objects, too.  I don't always do this, which made this more challenging for me.  But, again, you certainly can solve this issue without my technique as long as you can identify the Child Object by their unique ID at Save time.

I also agree that the UI isn't the place for the responsibility of maintaining the indexes.  But it MUST provide the object that does the index maintenance with enough information to determine what needs to be done.  So, for example, if the user is performing an insert at position 2 in the list, the UI must be able to pass that information along somehow.  If they are making a simple addition at the end of the list, that information must also be passed along (but there are fine default methods in CSLA for this already, of course).  If you offer a Move capability or (Cut/Paste) to change location of the child, the UI must be capable of identifying the child object being moved and its target location.  These ARE responsibilities of the UI.  But assigning the proper sort index values to each child is NOT.

 

Copyright (c) Marimer LLC