Question about Editable Assignment object similar to ProjectResource

Question about Editable Assignment object similar to ProjectResource

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


dshafer posted on Monday, November 13, 2006

I've got a use case that requires a situation very similar to situation in the ProjectTracker application which uses the ProjectResource object to implement an assignment of a resource to a project.  I'm currently redesigning/rewriting this application using CSLA.Net and C# 2.0.  In the old version of this software the database was not properly normalized and therefore it was very easy to allow the user to edit all of the information for a particular table in 1 grid.  In order to normalize the database, I have split the table in question into two different tables similar to Resources and Assignments in the PTracker database.  In my particular use case the user would like to be able to edit the actual details of the base resource object along with those details that are specific to the assignment of the resource to that project (i.e. the resource's role).  To keep the functionality similar to that of the old system, the users would like to be able to modify, for example,  the resource's first name and also the resource's role on a project on the same screen in the same grid.  My problem arises when I try to setup these objects....I'm not sure how to modify the PTracker example to allow for the editing of both the assignment object (ProjectResource) and the "base" object (Resource).....Can anyone offer insight or point me in the right direction?

Bayu replied on Tuesday, November 14, 2006

Hey there,

It looks like you fell in the classic trap of modeling objects after your datamodel .... while you _should_ be modeling them after your use-case.

In other words: if your use case is to allow the user to edit a resource's role and name, then create a business object Resource with a Role property and a Name property. In your dataportal_xxx methods you can put the normalization into effect by wrapping as many inserts/updates as needed to get the job done in a single transaction.

Or in case you are working with stored procedures: put multiple queries in the body of your proc.

Regards,
Bayu

dshafer replied on Tuesday, November 14, 2006

I had previously thought about using a single business object to encompass this functionality but I guess I figured that since the ProjectTracker app used the Resource class, the ProjectResource class, and the Assignment class, that I should model my "assignments" in a similar fashion.... I guess the fact that I need to be able to edit information from both the original table and the assignment table in the same grid makes my scenario different from the ProjectTracker sample as it only allowed the user to modify the "assignment" information on one screen and the specific resource information on another.  Thanks for the advice, I'll see if I can get it going with just one class.

Bayu replied on Tuesday, November 14, 2006

Aha,

I can see why this is confusing.

However, you should note the following:
- Assignment is not a class .... it's just a module that provides functionality to Add/Remove/Update Assignments in a shared location
- the ProjectEdit view uses its own set of BOs (Project - ProjectResources - ProjectResource)
- and ResourceEdit also (Resource - ResourceAssignments - ResourceAssignment)
- both ProjectResource and ResourceAssignment deal with the same database table in the background: the assignments table, it is important to note that although there is 1 table, we still have different BOs for each view (i.e. BOs are modeled after use cases).
- the Assignment module is used by both ResourceAssignment and ProjectResource and I think the only reason for putting the assignment-crud functionality in this module is to avoid duplicate code.

Good luck refactoring! Wink [;)]

Regards,
Bayu

dshafer replied on Tuesday, November 14, 2006

I started implementing this functionality as one object/class based on use cases instead of database design and have run into the following situation....My database has the following tables (names were changed to protect the innocent):

Resource, Assignment

The problem comes about when I attempt to implement optimistic locking similar to what Rocky implemented in ProjectTracker.  Basically I have a timestamp column in each of the tables that indicates when the last change was made.  If I use one business object to handle this which is able to update information from both of the database tables, I will have to have two timestamp/ byte[] fields on my business object.  Is there any better way to handle this, or is my approach acceptable?

 

ajj3085 replied on Tuesday, November 14, 2006

I would say having both timestamps is fine, after all its information that the BO needs to complete its task.

The timestamp fields in your BO should be private, I can't think of a reason to expose them to the UI layer.

HTH
Andy

dshafer replied on Tuesday, November 14, 2006

Ok...That seems to have done the trick.  I do have a sort of related question about how to handle update conflicts associated with optimistic locking in the UI/presentation layer.  The user(s) will be modifiying a collection of objects in a grid.  The saving of the collection is performed as the user attempts to close the form...I currently have it working where the objects w/o update collisions will save successfully while the objects with update conflicts will not save.  I'm just trying to think of a good way to handle this update conflict situation in the UI....  The objects in the collection are child objects, and therefore cannot be "refreshed" individually...Any ideas on how to handle this sort of thing "gracefully" in the UI?

 

ajj3085 replied on Tuesday, November 14, 2006

Well, the typical route is to throw an exception if the optimistic locking fails.  Your UI catches it, says the entire operation has failed...

What to do next is up to you.  You can't save anything because part of the transaction has failed (which is fine)... so you may have to close the form, or have the UI reload from the database, which of course would lose all user changes.

If the latter is unacceptable to you, perhaps you need to rethink your design, because at that point it would seem that your children can be edited independantly and they should really be root objects.

Of course you can do something more sophisticated, like rollback the transaction after finding ALL the collisions, load up a 'diff' object, then show the user the collisions and allow them to attempt a merge.  Of course that will be a tough thing to code.. but no one said merging was easy.

Andy

dshafer replied on Tuesday, November 14, 2006

Ok...Thanks for the feedback... Now I have at least enough information to present to the team on this topic.

Copyright (c) Marimer LLC