I have an application where I have to keep track of an object's child items in two collections. One collection is the primary collection and is used to persist the objects, etc. The other is essentially used to "bucket" or categorize the objects for other purposes (statistical, logical, etc.). I am wondering what the most recommended approach is and, ultimately, what suggestions you have about which object should be in charge of maintaining the second collection.
The key is that when I add or remove an item from the primary collection, it needs to also be added or removed from the "bucket" collection - which is a multimap (collection of lists) simply holding references to the objects contained in the other collection grouped by a key field.
I won't lead the witness too much because I am very interested in hearing your opinions and approaches, so I will leave it at that for now.
Thx in advance.
Yea, I guess that deserved a better explanation.
The "bucket" collection actually contains "bucket" objects which contain the collection of items that are also contained by the primary collection. This is because the "bucket" object contains some additional properties that summarize or aggregate the "grouped" items. Oh, and all of this is in memory at once and dynamic, so we can't have a filtered list that represents bucket1 and a separate one that represents bucket2 and so on.
Let me try to represent what we have going on:
RootObject
Items As PrimaryCollection (of ChildItem objects)
Buckets As BucketCollection (of Bucket objects)
Bucket
SomeProperty
Items As PrimaryCollection (of ChildItem objects)
When we add a ChildItem to the RootObject, it is added to the PrimaryCollection AND somehow needs to be added to the appropriate Bucket in the BucketCollection (with a new one created if it doesn't already exist). So, who should be responsible for managing this?
The typical ways of adding a child item would be:
RootObject.AddItem(childItem);
RootObject.Items.Add(childItem);
Obviously the first gives us the ability to call the second plus call Buckets.Add(childItem) if that was the route we wanted to go. The latter would require us to hook up to ListChanged or some other way to handled when an item is added or removed because we shouldn't, imo, couple the PrimaryCollection to the BucketCollection (or should we)?
The former would require us to hide the Add, Remove, etc. methods from the two collections to avoid inadvertant use. So, all management functions would have to be handled by the containing object. But, they would still have to be exposed in order for the containing object (RootObject) to access them - declare them as internal???
Thoughts?
I am not familiar with the ObjectListView class. Can you explain it and where it is located?
It sounds like you are recommending having BucketCollection implemented so that it is responsible for listening for changes in the associated collection. Then, based on the filter "rules" applied, it will perform an action, such as adding and removing items, as well?
Also, how do we handle a case when a new item is added to the RootObject's PrimaryCollection that doesn't have a corresponding bucket yet? Ultimately, this is how the bucket objects will come into being:
Likewise when an item is removed. If that is the last item in the bucket, the bucket should also be removed.
To go with your example, let's say our objects are Person classes with a LastName property. If we are creating buckets for the last name, our filtering would be on that property and, as you've shown, something along the lines of "LIKE A%". HOWEVER, we don't know the criteria up-front. It is only as items are added that the criteria is established. In other words, we wouldn't create 26 buckets with 25 empty if our only item was Bob Smith. In that case we would only have one bucket defined for the S% items. Should John Doe be added to the collection, we would then create a bucket for the D% cases.
I guess using a name is a bad example because our filtering would never be as finite as A-Z. It could be numeric based and of any range.
See my dilemma?
This is a great tool. I like what I've seen so far except that I have a problem when loading my objects from the database. The reason is that the child collection uses lazy-load to retrieve the data for its child objects. Because of this, we don't attach the ListChanged handler in our RootObject until AFTER the factory method has completed the DataPortal_Fetch call and already populated the collection. As a result, our buckets are empty.
Obviously, I can get rid of the lazy-load and have the data loaded with the RootObject, but I'd like a solution that keeps the door open for both options if possible. This is not the only child collection that we may use this approach for and there's a lot of data, so lazy-loading has been our best solution to improving the responsiveness of each individual operation.
Can you think of a way to accomplish the same thing given a lazy-load approach?
Two questions about the ObjectListView:
sorry, one more... Why not a generic implementation?
Brian, thanks for indulging my questions. This is a great addition to the Csla framework.
Copyright (c) Marimer LLC