Hello:
Background:
I have a custom user control based around a WPF TreeView. I've been using the MVVM pattern and have a base view model TreeNode
class and several derived view models such as LocationNode, LocationFolder, PersonNode, PersonFolder, CollectionNode, CollectionFolder, etc..
A example of how the tree might be laid out is:
- CollectionFolder
--> CollectionNode
--> LocationFolder
-->LocationNode
-->LocationNode
--> PersonFolder
-->PersonNode
--> CollectionNode
--> CollectionNode
+ CollectionFolder
+ CollectionFolder
When I perform drag and drop operations, each class handles the business logic, i.e. if I drop on a PersonNode
on a CollectionNode
, the CollectionNode
view model contains the logic how on to add the PersonNode
it its child PersonFolder
.
Problem:
Everything works great, I can drag and drop all over the place, and the code is nicely contained in the dervied classes. If I need to add an extra drop rule, I add it to the appropriate drop target view model.
The problem is when a PersonNode
is added to a PersonFolder
I need to create a new database entry to reflect that the underlying Person
model is now in also in a new Collection
.
Currently, each view model in the tree has access to the current database session/transaction and can perform the insert/save. But this makes catching exceptions and errors extremely repeative, my exception handling code is being duplicated all over my view models. Is there a better way in MVVM to handle my database interactions?
An code snippet from my Drop
event in my PersonFolder
// Create a new view model for the Person and add it to my children
_children.Add( new PersonNode( droppedPerson ) );
// Create a new entry in the collection for this person
CollectionEntry entry = new CollectionEntry();
entry.Entity = droppedPerson;
entry.Collection = _collection;
// Save the new entry
using( var transaction = _uow.BeginTransaction( IsolationLevel.Serializable ) )
{
// Add the entry to the session
_uow.Add( entry );
// Save the session
_uow.SaveChanges(); // [1]
// Commit transaction
transaction.Commit(); // [2]
}
[1] and [2] have the potential for throwing exceptions and should be handled in try/catch statements. However, I don't want to duplicate all my exception handling in all my view models, any suggestions?
I guess I could always implement a singleton to contain the session and exception handling and pass my new entities into that?