Single page, Multiple Lists, Single Business Object

Single page, Multiple Lists, Single Business Object

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


BillArms posted on Monday, March 19, 2007

Hello to all,

I have searched the forums, FAQ and wiki and did find a discussion that touched all the issues that I have. One came close, http://forums.lhotka.net/forums/thread/10131.aspx , but did not really answer my problem.

Back ground - I am using CSLA 2.14, C# and ,NET in VS2005.

The GUI is to have seven grid views populated by different lists of the same editable root business object, an ICSR.  The lists are not guaranteed to be mutually exclusive.  The user will edit attributes on the ICSR (plan on Master-Detail) but will not add or remove them from the list. Changes will sent to the database after the presses a "Recompute" button

I have implemented a BO collection for entire list of all ICSRs.  It appears to be functional. but not yet fully tested.

Each of the seven lists can be obtained from a single stored procedure by passing it a single parameter. Any changes to the conditions which drive the contents of the lists will be made in this stored procedure.

There are two issues, perhaps interrelated, as I see. First, is should I build a separate class for each of the lists or should I build a single object which would return separate lists based on parameters? The second issue is since there are seven lists on one page and the user may be changing ICSR attributes in differing manners for the same ICSR on different lists, is there an architecture/design which lends itself to comparing and resolving discrepancies?

I expect few changes to the business rules of the lists once the differing attributes resolution is handled.

Quick responses are appreciated. As always, there is a drive to complete sooner rather than more correctly. The old code-first design-later syndrome.

Regards,
Bill



Bayu replied on Tuesday, March 20, 2007

Hey Bill,

Based on the information you provided so far I would suggest to follow an MVC approach:

Model (M):
- 1 list containing ALL your ICSRs
- so the superset of all ICSRs that may be displayed in one or more of your grids

View (V):
- each grid is one particular view on your model
- the view is responsible for filtering out those ICSRs that are relevant for this particular grid
- note: this is different from filtering in your sproc, your sproc fetches everything, it's only in the UI that you start filtering

Controller (C):
- if you use data-binding to connect all your views to the same model (your single list of ICSRs) the different views will be synchronized automatically (!).
- this is why I strongly recommend this approach (especially as you indicate to be in a hurry ;-) ), this way databinding can solve the challenge of keeping everything in sync
- the Recompute button is the other part of your (conceptual) Controller, it will commit any changes to your model to the DB (not sure if you persist anything, you didn't mention it actually, but at least some computation-routine will be triggered here)

Good luck!
Bayu

Bayu replied on Tuesday, March 20, 2007

Oh,

In addition to my previous post, an additional tip came to mind:

Check the FilteredBindingList that should available somewhere on this site (download page or Codeplex, dunno)
- I never used this since I use the highly capable grids from infragistics, but it may very well serve you
- you would then still have this 1 list of ICSRs as your model
- subsequently you would have 7 FilteredBindingLists, one for each grid. Each with their own set of filtering settings
- the BO (ICSRList) would be the datasource of all these filteredbindinglists, and each grid would have a filteredbindinglist as its datasource

I am pretty sure this could be made to work wonderfully.

;-)

Bayu

SonOfPirate replied on Tuesday, March 20, 2007

A better understanding of your use-cases may lend itself to a better answer, but based on what we know, I would agree that having a single BO that contains a "master" list, so-to-speak, with each of your grids bound to a view based on that BO using whatever filtering/sorting/grouping criteria you have would be the best and simplest way to go.  This is, of course, assuming that the resultset returned from your sproc is also singular in nature - which I am not sure is the case.

I am concerned because of your indication that "each of the seven lists can be obtained from a single stored procedure by passing it a single parameter."  Does this mean that this parameter is used to conditionally execute statements within the sproc?  In other words, is this parameter a switch-case type argument that indicates which execution path to follow?  If so, then I am going to recommend breaking this into seven separate sprocs with seven separate BO's as there would be seven use-cases to satisfy.  If not, then I defer back to the original suggestion.

HTH

 

BillArms replied on Tuesday, March 20, 2007

Bayu and SonOfPirate, thank you for your replies.

A quick description of the use case follows:  The financial admin actor is deciding which attributes on specific ICSRs to set or unset. They will use the information displayed on the single page, the seven lists and other information to aid their decision.  The seven lists are various process states for the ICSRs.  The changed attributes of the ICSRS will be persisted. A complex 'rolling up' is then initiated, the new results displayed and the iterations continue until the fin admin is satisfied.

The single stored procedure parameter is, in effect, the name of the list to return.  The filtering is somewhat complex and for performance reasons is best done on the database. The filtering is also based on information which is not contained within the ICSR business object.

Does this addition information affect your recommendations?

Your replies are truly appreciated.  It is amazing how other peoples perspectives can bring clarity to one's own thoughts.

Regards,
Bill

BTW SonOfPirate, I attended University of Michigan from 68 to 70. Go Blue!


SonOfPirate replied on Tuesday, March 20, 2007

Ah, then you were there for "THE Game", eh?  Unfortunately I was there during some leaner years during the late 80's/early 90's.

Anyway, from what you describe I would definitely suggest the single collection BO, multiple views approach.  If I understand you correctly, it sounds like you are simply breaking your master list into smaller lists based on state.  This would be consistent with this approach where each view would correspond to a particular state.  When the state of an element changes, you would only need to refresh the views based on the updated collection and your UI would update accordingly.

HTH

 

BillArms replied on Tuesday, March 20, 2007

So to restate the recommendations (as I understand them):

Use master BO list of all ICSRs.  Since the filtering is done on the database, I will need to use seven BO lists to display the seven ICSR state lists on the page. When the user changes the attributes of an ICSR on a given list, I change the applicable ICSR state list and the master list (all cached server side). When the user presses the recompute button, I save the master list to the database, initiate the 'Roll up" and redisplay the page for the next iteration.

Is my restatement correct?

Regards,
Bill

Wikipedia has a full discussion of the Michigan-Ohio State history. OH, how I hate Ohio State!

BillArms replied on Tuesday, March 20, 2007

The seven lists are NOT mutually exclusive.  The same ICSR may appear on  more  than one list.

BillArms replied on Tuesday, March 20, 2007

My comments in 13317 were made before I read 13316 (it was not there when I started writing the post, editorial overlap :) )

The lists are based/filtered on conditions on other tables in the database.  To move that logic into a filtering list BO would cause cause poor performance because the BO would have many database calls.  While the user edits the ICSRs, the lists are static (no additions or removals). After the recompute, the contents of the list may vary due to ICSR attributes changing.

Regards,
Bill

BillArms replied on Tuesday, March 20, 2007

An idea, I could get the DBA to give the ICSR a boolean attribute for each list.  He could modify the stored procdure for generating the lists to update the attribute.  The ICSR master list could then easily be filtered using the FilteredBindingList. I could then implement Bayu's suggestion.

Sound feasible?

Regards,
Bill

SonOfPirate replied on Tuesday, March 20, 2007

I was on the same page with Bayu expecting that the stored procedure would return a single resultset and filtering would be done by the FilteredBindingLists based on the master list BO.  I'm still not sure we have a clear picture of what you are doing in the db and this may be causing some of the discrepencies.

Are you returning a single resultset from the db or seven resultsets - each corresponding to one of the filtered lists you are displaying?  From your description, it sounds like you are returing seven separate "lists" from the sproc.  I guess this is where both Bayu and I are raising our eyebrows.

In your last post it sounds like you are thinking of combining these resultsets into a single resultset with an additional column that can be used to filter the master list into the seven "filtered" lists in your BO.  If I am on the same page, then it sounds like this is a step in the right direction because I think the simplicity and synchronization benefits that you get going with the single BO with multiple views are significant.

HTH

 

Bayu replied on Wednesday, March 21, 2007

Clever!

That way you leverage the DBs filtering capabilities AND the synchronization inherent to databinding without too much trouble.

I like it. ;-)

Let us know if it is any successfull!

Regards,
Bayu

Jimbo replied on Wednesday, March 21, 2007

I thought that there is a protocol for the  use of acronyms. When they are introduced, it is important to spell out the long description ICSR (? Blah). Then perhaps we can all relate better. Many discussions can become too esoteric.


Bayu replied on Wednesday, March 21, 2007

Jimbo:
I thought that there is a protocol for the  use of acronyms. When they are introduced, it is important to spell out the long description ICSR (? Blah). Then perhaps we can all relate better. Many discussions can become too esoteric.




LOL :D

Actually, I too have absolutely no idea what it is. ;-) It didn't matter for the purpose of the discussion though. ;-)

Google tells me it can be any of this:
- Institute of Control and System Research
- International Conference on Software Reuse
- Indian Cultural and Rock Society
- Individual Case Safety Report

Bugs me ....  most probably it's none of the above. ;-)

Bayu


BillArms replied on Wednesday, March 21, 2007

Sorry Jimbo,

I did not spell out the meaning to ICSR mostly because, to me, it is just a business object to be manipulated.  To tell the truth, when I asked the boss/client, he was not sure what it meant.  It is the financial grouping of workorders and authorizations to proceed (ATP). The ICSR is used to allocate funding to a project. For purproses of the discussion , it can be treated as a generic editable root business object with attributes.

Regards,
Bill

Bayu replied on Wednesday, March 21, 2007

BillArms:
Sorry Jimbo,

I did not spell out the meaning to ICSR mostly because, to me, it is just a business object to be manipulated.  To tell the truth, when I asked the boss/client, he was not sure what it meant.  It is the financial grouping of workorders and authorizations to proceed (ATP). The ICSR is used to allocate funding to a project. For purproses of the discussion , it can be treated as a generic editable root business object with attributes.

Regards,
Bill



Whaahaaaaaaaaaaaaaaa LOL :D :D

We can be the most genius guru around, and still have no clue what we're doing.

Isn't it great that nevertheless we can still solve these issues!

Magic ......


BillArms replied on Wednesday, March 21, 2007

I always liked the term "Universe of Discourse".  I first saw it the Object Oriented Modeling and Design book by James Rumbaugh.  We can not model the entire universe, so we limit the discussion to what we believe is relevant.  Myoptic vision can be useful  :)

Regards,
Bill


BillArms replied on Wednesday, March 21, 2007

Back to the well for another dose of good information.

The isue now is the linking of the seven filtered lists, the gridviews, CslaDataSources and the MasterList.

I have modifed the ICSR object to contain booleans indicating specific list membership and propagated that change into the ICSR BO. 

I created a filter provider.

public class IcsrListFilter
{
  public static Boolean Filter(object item, object filter)
  {
    return (item.Equals(filter));
  } // end Filter method
}

And I added the lists to my code behind page.

  private WODB_Library.Finance.ICSRList MasterList = null;
  private FilteredBindingList<ICSR> Over120DayList = null;
  private FilteredBindingList<ICSR> BudgetOkList = null;
  private FilteredBindingList<ICSR> ProDayList = null;
  private FilteredBindingList<ICSR> Twixt100_108List = null;
  private FilteredBindingList<ICSR> Twixt108_100List = null;
  private FilteredBindingList<ICSR> ExcludeList = null;

  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
      this.mvMain.ActiveViewIndex = 0;
      itCurrent.Fetch();
      AssignTotalValues();
      AssignListValues();
      isDirty = false;
    }
    else
    {
      if (isDirty)
      {
        itCurrent.Fetch();
        AssignTotalValues();
        AssignListValues();
        isDirty = false;
      }
    }

  private void AssignListValues()
  {
    MasterList = GetICSRList();
    SetFilteredList(ref Over120DayList, "Over120DayList", true);
    SetFilteredList(ref BudgetOkList, "BudgetOkList", true);
    SetFilteredList(ref ProDayList, "ProDayList", true);
    SetFilteredList(ref Twixt100_108List, "Twixt100_108List", true);
    SetFilteredList(ref Twixt108_100List, "Twixt108_100List", true);
    SetFilteredList(ref ExcludeList, "ExcludeList", true);
  }

  private void SetFilteredList(ref FilteredBindingList<ICSR> list,
    String property, Boolean filter)
  {
    list = new FilteredBindingList<ICSR>(MasterList);
    list.FilterProvider = IcsrListFilter.Filter;
    list.ApplyFilter(property, filter);
  }
 
 
  Now the questions are: How do I connect the FilteredLists to the gridiews? and What CslaDataSources do I make and how do they connect?
 
  Regards,
  Bill

kids_pro replied on Wednesday, March 21, 2007

I woud set it like this:

gridView1.DataSource = Over120DayList;
gridView1.DataBind();

Bayu replied on Thursday, March 22, 2007

Hey!

Your masterlist can be replaced by the CslaDataSource.

It's been a long time ago since I worked with ASP.Net, but I believe it raises a SelectObject event (or something akin) which allows you set the source for this CslaDataSource. That would then have to be your ICSRList BO.

Schematically it would have to look like this:
1 - BO --> CslaDataSource (aka 'masterlist')
2 - 7 times CslaDataSource --> FilteredBindingList
3 - 7 times FilteredBindingList --> GridView

1 can be achieved by soime event like I mentioned, 2 is what you pretty much put there already and how to do 3 was mentioned by kids

Good luck! ;-)
Bayu


-

Bayu replied on Tuesday, March 20, 2007

BillArms:
So to restate the recommendations (as I understand them):

Use master BO list of all ICSRs.  Since the filtering is done on the database, I will need to use seven BO lists to display the seven ICSR state lists on the page. When the user changes the attributes of an ICSR on a given list, I change the applicable ICSR state list and the master list (all cached server side). When the user presses the recompute button, I save the master list to the database, initiate the 'Roll up" and redisplay the page for the next iteration.

Is my restatement correct?

Regards,
Bill

Wikipedia has a full discussion of the Michigan-Ohio State history. OH, how I hate Ohio State!


In my opinion you are mixing up two solutions, into something quite interesting though! ;-D

I meant this:
- one master list
    - is loaded used just 1 sproc
    - no filtering on DB

- 7 FilteredBindingLists
    - each one sits between the materlist and one grid
    - it is here that the filtering is done

The good:
- databinding will keep everything in sync (masterlist, filteredlists and your 7 grids) which is a HUGE pro imo
- upon recompution you need to commit just the masterlist to your DB

The bad:
- you say you prefer filtering in the DB, this part is lost in my proposal. How bad this is .... up to you to decide

If you take the 'usecase centric approach' you could consider the following:
- extend your BOs with any property that is necessary by the UI to appropriately apply the correct filters (this is what modeling after use cases is about, get BOs to support your UI)

Your restatement is basically the alternative that uses 7 sprocs and filtering in the DB. In your case the masterlist is going to involve a lot of overhead, as you will have to programmatically keep things in sync.

Mind that I have no clue what kind of filtering and what performance comparisons we are looking at. Just throwing a (theoretically valid) alternative in the box. ;-)

Regards,
Bayu

Bayu replied on Tuesday, March 20, 2007

Hi,

I am getting confused, I thought you were saying that 1 ICSR might be displayed in more that one of your 7 grids. Am I correct?

My former suggestion was centered on the idea that you could leverage databinding to do all the synchronization for you. If however the 7 lists are distinct, in the sense that they have no overlapping records (e.g. an ICSR can only be in exactly 1 of 7 states), then things might be different.

In the latter case no synchronization would be necessary and perhaps different arguments should be favoured. On another note, your comment that 'some of the filtering is best done on the DB' sounds like you are modeling your UI-logic based on DB-constraints (i.e. data-centric), which is never a good idea.

Maybe you should bounce some more info around on this thread?

;-)

Bayu

Copyright (c) Marimer LLC