parent and children

parent and children

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


maur33n posted on Friday, June 06, 2008

I am not sure how to search on this question so please forgive me (or post a link to the thread) if this has been asked a thousand times already:

I have a Customer, Project list.  The Customers are parents that each have their own project list.

I believe I should then do the following:

1.  a. create Customer class using BusinessBase
     b. create CustomerList using BusinessBaseList

2.  a. create Project class using BusinessBase
     b. create ProjectList class using BusinessBaseList

3.  CustomerList should have a Fetch with _customerList populated via SP_GetAllCustomers
 
4.  Customer should have a Fetch with _projectList populated via the datareader sproc that does say,   SP_GetAllCustomersByCustomerId.


So now I would have to call the CustomerList Fetch, which gives me a list of all customers.  Then looping through that list, get the customer id, and use something like

  Customer cust = Customer.GetCustomer(c.Id);

Then

  ProjectList prjList = cust.ProjectList

To get my projects list by customer.

However, I now want to use the update functions.  I have marked the ProjectList class as child to Customer.

But you can't update the child.  So am I supposed to put the update in the Project class? But isn't the Project class a child of ProjectList?  I'm confused.  I think the goal is to reduce the number of trips to the database--so if that is the goal, why not just use the Customer class to populate the CustomerList, using a sproc that grabs all customers and all projects, and pass that datareader to the Project/ProjectList? 

Thing is, what if I _just_ want the one customer and it's project list?  Now I've gone and gotten what could be, say, 3000 customers and all their projects just to get this one customer/projectlist.  So I as it stands now, my code doesn't do that.

Is there a better way to do this?  I can't see the forest for the trees right now :)


maur33n replied on Friday, June 06, 2008

This is what my code does now, and explains what I'm trying to say--but it doesn't "smell" right. In other words, I thought, based on my reading, that I should be able to update ProjectList once after I have "dirtied" the Projects rather than calling a separate Save on each project.  I would think I should do a ProjectList.Save().  Right?  But it's a child. 


    CustomerList custList = CustomerList.GetCustomerList();
                foreach (Customer c in custList)
                {
                    Customer cust = Customer.GetCustomer(c.Id);
                    ProjectList prjList = cust.ProjectList;
                 
                    foreach (Project p in prjList)
                    {
                        Console.WriteLine(c.Id + " " + c.Name + "      " + p.Id + "-" + p.Name + "-" + p.City);
                        p.Name = p.Name + " - updated";


                        p.Save();//because prjList is a child of customer, can't update there, so updated project instead
                    }

                }

Lalit replied on Friday, June 06, 2008

Hi,

In your scenario where CustomerList is root object, it will populate data for its every child(i.e. Customer object). CustomerList will have a DataPortal_Fetch method, which will fetch data from DB for all customers. Now your customer object will have a Get method which will take SafeDataReader as its argument to populate its data, fetched in DataPortal_Fetch method of CustomerList. Call for Get method of Customer in DataPortal_Fetch method will be something like

while (dr.Read())

{

this.Add(Customer.GetCustomer(dr));

}

 

This GetCustomer method will populate itself and will call a Get method for its child list(i.e. CustomerProjectList). This code need not to be in DataPortal_XYZ method as it is being called from its parent's DataPortal call. In the very same way CustomerProjectList also will take responsibility to populate its children itself.

Now CustomerList is parent object and others are child, you can call save only on CustomerList. To handle this save call you have to write DataPortal_Update method for CustomerList object. this method will call "non data portal" Insert or Update methods of Customer whih will call SPs to insert or update the customer. These Insert or Update methods have to call some method responsible for saving its child list(i.e. CustomerProjectList).

DataPortal_Update()

{

   foreach( Customer child in this.DeletedList)

   {

      if(!child.IsNew)

         child.Delete();

   }

   this.DeletedList.RemoveAll();

   foreach( Customer child in this)

   {

      if(child.IsNew)

         child.Insert();

      else if(child.IsDirty)

         child.Update();

   }

}

The essence is parent should handle fetch and save operations for its children and DataPortal_XYZ methods ensure that code written in them will be executed only on server. So if a method is being called in some data portal call, it also will execute on server and not on local machine.

maur33n replied on Friday, June 06, 2008

Thank you for your response....mulling this over...


maur33n replied on Friday, June 06, 2008

Is this correct?


query:

Customer:  Data Portal call to query sproc
CustomerList:  datareader
ProjectList:  datareader



update:

CustomerList:  DataPortal call to update sproc

maur33n replied on Friday, June 06, 2008

>>Now CustomerList is parent object and others are child, you can call save only on CustomerList. To handle this save call you have to write DataPortal_Update method for CustomerList object.

 So my only update data portal which hits the server is in CustomerList.  Okay.


 >>this method will call "non data portal" Insert or Update methods of Customer whih will call SPs to insert or update the customer. These Insert or Update methods have to call some method responsible for saving its child list(i.e. CustomerProjectList).


Here is where  I get lost.  I have another update/insert in Customer? Is the Customer update/insert a Data Portal method that hits the server using a stored procedure?

But you just said the only server update with sproc is in CustomerList.  Hmmm.  Am I reading you wrong?

(When you say Data Portal, I assume you mean this is where I have an actual stored procedure that hits the server.  When you say non-Data Portal, I assume you mean I am updating the object in memory and will call a "real" data portal with stored procedure update in another class).

Lalit replied on Friday, June 06, 2008

>>Now CustomerList is parent object and others are child, you can call save only on CustomerList. To handle this save call you have to write DataPortal_Update method for CustomerList object.

 So my only update data portal which hits the server is in CustomerList.  Okay.

=> Yes your DataPortal_Update will be only in CustomerList, which in turn calls respective methods of its child. and hence that code also will execute under data portal. Thats why u need not to call child's Insert/Update methods in DataPortal calls.

 

It will be something like

Public void Insert()

{

   Executing your SPs here to save customer.

   Now call some non-dataportal save method for CustomerProjectList().

}

 

As this Insert method is called in DataPortal_Update of CustomerList, this code also will execute on server itself.

Now save method for child list(i.e. CustomerProjectList) will be something like

public void SaveList()

{

   Here code will be similar to DataPortal_Update of CustomerList.

}

 

The reason for not moving this save list call under DataPortal is same again.

 

Hope this will make the point clear. You can look for the code in ProjectTracker example provided.

 


 

 

maur33n replied on Friday, June 06, 2008

Hey, you know what.  What I really need is to fill in these blanks:

Customer
     Query:  dataportal
     Update: datareader or dataportal?
CustomerList
     Query:  datareader
     Update:  datareader or dataportal?
Project
     Query:  datareader
     Update: datareader or dataportal?
ProjectList
     Query:  datareader
     Update:  datareader or dataportal?

maur33n replied on Friday, June 06, 2008

 I understand now.

 Thank you.  I think I had a mental block because the example code in ProjectTracker shows a webform update of roles.  But before you can update one role, you have to do a GetRoles, which calls a stored procedure to return you all the roles.  Your explanation does the same, from what I can see.

It just isn't something I feel good about, on gut instinct, and I therefore read it and dismissed it without thinking.  I'm used to grabbing an object id from the UI, then calling a stored procedure to update that one row.




maur33n replied on Friday, June 06, 2008

quoting myself:

"I'm used to grabbing an object id from the UI, then calling a stored procedure to update that one row."

I suppose I can still do that with a GetProject(Guid id) method. 

A little fuzzy now in my head as to why the book shows GetRoles() and loops through all roles to find the right one to update, then later as I read I see a completely different example of where the UI passes a specific id to the Get method and executes the stored procedure.

I'm one of those nutty people that really has to know the "why" before the "how" because I stop listening to "how" if I don't know "why".

I'm still a work in progress :) 

Does anyone know what I'm talking about, or am I just a rambling old lady...


Lalit replied on Friday, June 06, 2008

Hi,

I think your prob was something different. Let me take an other example.

If there is a scenario where a Customer class have some properties with a list of projects running under it. On first page i have to show a list of Customers. with selecting one Customer i can go to another page where apart from Customer's all properties i will display list of projects also. One can edit the Customer here. From this page if i want to edit a project listed for that customer, i will select a project and will go to third page to edit project itself.

Here i will prefer to define a ReadOnlyListBase of Customer's ReadOnly objects(e.g. CustomerInfo as ReadOnlyBase and CustomerList as ReadOnlyListBase). These CustomerInfo objects will be child of CustomerList. CustomerList will have DataPortal_Fetch method, which will call a SP that will return a datareader containing records of all customers but not the Project information. Now using this datareader i will make a CustomerInfo object for each row in datareader and add it in the list. As this is ReadOnlyList forget about Updation of this list. These objects will be used for first page.

Now for editing customer data i will define a BusinessBase class(Customer). Apart from properties of customer it will also hold an object of Projects(BusinessListBase Class which will represent an editable list of projects). Hence the relationship between Customer and Projects will be that Projects is child collection of Customer. As Customer is root object it will have a DataPortal_Fetch method which will querry the DB using a SP and fetch data for selected customer and all the projects of this customer. Now after populating this Customer object u will pass dr.NextResult() to Projects collection. This collection will populate its children and add them to itself.

Rest you can find in previous replies.

 

Now what i am feeling is u must be confused with a UI code where i will fetch CustomerID from selected ReadOnly CustomerInfo object listed in grid on first page. Using this ID i will fetch only that Editable object which i have to  edit and not all objects iteratively.

Through this approach i can acheive conditional loading of data. As i am not fetching the data for projects untill and unless i am going to edit the customer where i have to display projects as well.

 

I think that can help you to understand why the things are so.

Lalit replied on Friday, June 06, 2008

I am updating the Qs according to  hierarchy from Parent to Child.

CustomerList
     Query:  dataportal(will fetch data in drParent)
     Update:  dataportal
Customer
     Query:  datareader(drParent) with a method call for ProjectList
     Update: public method with SPs to do the updation.
ProjectList
     Query:  public method with SPs to fetch data in drChild
     Update:  public method with SPs to do the updation.
Project
     Query:  datareader(drChild)
     Update: public method with SPs to do the updation.

maur33n replied on Friday, June 06, 2008

Yes, that is very clear.  See my last post as well--I looked at the sample code again to make sure I understood. 


thank you so very much for taking the time.  It really is a big help and you have made a big difference in my understanding!

Copyright (c) Marimer LLC