Root and Child Objects in CSLA

Root and Child Objects in CSLA

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


Ashraf Ali posted on Sunday, February 11, 2007

Hi,
I am coding a VB.NET application for which the database and its Stored procs are already written, The way the Stored procs are written, I can't possibly use the root and child objects as defined in the CSLA , because of the fact that every object should contact the Database by itself. The reason behind this is the Stored procs are pretty simple and return data for an object or a collection of objects.

 Any suggestions? or Any one encountered the same problem?

Thanks

Ash

William replied on Sunday, February 11, 2007

Since the stored procedures are written to return object and collection data. I don't quite understand why root/child objects could not be created. Perhaps, you can try to elaborate more.
 
Regards,
William
 

Ashraf Ali replied on Sunday, February 11, 2007

William,

I can probably understand why are the Stored procs like that, because if we follow the root and child objects model as we have in CSLA, then I will have one root object and 7 child obects, 4 child collection objects and 3 grand child collection objects, so apparently loading all these objects won't be a good idea?? (right? wrong?) considering its a web app.

Now coming to the question why I can't create root/child objects? It was not quite intuitive to me either :) :) because then all the stored procs (for the objects as I explained above) will be called by the root object, right ?

thanks

Ash

 

JonM replied on Sunday, February 11, 2007

Ash,

The simplest way to handle this is to only have root editable objects and simply ignore child objects altogether.  Or put root collections inside of root objects.  The down side is that you lose transaction support meaning that a bug/crash could leave your parent and child objects in inconsistent states.  I would strongly recommend writing additional stored procedures (at least for the fetch/update procs).

Ashraf Ali replied on Sunday, February 11, 2007

JonM,

Thanks for your help, Do you suggest

1) rewriting some of the stored procs like we have example Stored procs in ProjectTracker?

2) or using Trasactions (COM+) in VB.NET code (as supported by CSLA)

Thanks

Ash

Tray replied on Monday, February 12, 2007

Hi Ash,

Another option could be to call more than 1 stored procedure in the data access section of your root object. If there is a stored procedure to retrieve the child data seperatly, you should be able to call one (existing) stored procedure to get the root object data and then call another to get the child data. e.g.

Protected Overloads Sub DataPortal_Fetch(ByVal criteria As Object)
Dim crit As Criteria = DirectCast(criteria, Criteria)

'Load values from db
'Open connection to db
Using cn As New SqlConnection(Database.Deed)
   cn.Open()

   'Set up command object
   
Using
cm As SqlCommand = cn.CreateCommand
      
With cm
         .CommandType = CommandType.StoredProcedure
         .CommandText =
"getClient"
         
.Parameters.AddWithValue("@clientCode", crit.ClientCode)

         'Retrieve root object information
         
Using
dr As New SafeDataReader(.ExecuteReader)
            With dr
               .Read()
               mClientCode = .GetString(
"clientCode")
               mClientName = .GetString(
"clientName")
               mInactive = .GetBoolean(
"inactive")
               .GetBytes(
"lastChanged", 0, mLastChanged, 0, 8)
            
End With
         
End Using

         'Reset command object
         
.CommandText = "getClientChildren"
         .Parameters.Clear
         'Add any other parameters required for the child call including parent identifier

         Using dr As New SafeDataReader(.ExecuteReader)
            'Pass datareader to child collection
            mClientChildren = ClientChildren.GetClientChild(dr)
         
End Using

      End With
   End Using

End Using

End Sub

Instead of using the .NextResult method to move to the next datareader result, grab the data as an independant datareader and pass that to the child collection - the collection will not know the difference.

Remember that the Data Access section allows you to do anything to retrieve the data required. The object won't know the difference, and neither will its children. You could pull each child in a separate call if you wanted to, but that would be very wasteful.

I think that you should be able to use your existing stored procedures to retrieve the data that you need, you just have to plan how you are going to transform the data from the database into the objects, and this is what the Data Access section is for (or that's what I use it for with existsing db's)

Just thought I'd suggest a different approach. The more options the merrier Smile [:)]

Ashraf Ali replied on Monday, February 12, 2007

Thank you Tray, its so nice of you,
I will definitely follow the solution you suggested.
Ash

ajj3085 replied on Monday, February 12, 2007

Ash,

Csla is pretty flexible.  I'm not quite sure what your procs return now, but you should be able to use them without modification.

If they return the root and child objects all in one dataset, you call that procedure in the root's DP_F routine, and pass the result set to child collection which will use it to create child objects (also from the dataset).

If your procs return only one row at a time, Csla can handle that to.  Your child would then know the sql to load itself, and the collection need only get a list of ids of the child rows to load.

So, tell us what your procs do, and I'm sure we can figure out some way to  use them without modification. 

xal replied on Monday, February 12, 2007

Well, do consider also the fact that you may not need all that data at once. This is specially true in a web environment, where you usually want to avoid cluttered web pages, so you probably won't display a root with all it's 3 child collections and each of it's children child collections. This is also specially true if you are using session to store the objects, because you'll have a much bigger footprint in your session for no particular reason.

So, the questions you should ask yourself are "What is really my use case? how will these objects be used? For what purpose(es)?"

Perhaps it is the case that you need some of those items as child collections, and some as standalone collections. Perhaps you realize that you don't really need them as child collections.

It is true in most cases that you don't need to load such a deep hierarchy as you mention. It's just that the way the data is structured leads you to thinking that way.

Perhaps you could design your structure as you mentioned, but only load children on demand (Lazy Loading).


Anyway, there are different ways of doing the same thing, you just need to figure out what's best for you.


Andrés

Ashraf Ali replied on Monday, February 12, 2007

ajj,
consider a simple scenareio in my app,
One of stored proc returns data for the client, which is a root object,  what I do is, store that clientid in session.

Other stored procs returns result sets for orders and  Income info about client which are child collections of the root object, each of these stored procs requires clientid, so I pass them the clientid which I had already stored in session.
This is a very simple example, just to illustrate the point
Thanks
Ash

Bowman74 replied on Monday, February 12, 2007

Ash,

There is no reason why CSLA child collections and child objects cannot handle their own persistence without any modification to the CSLA base classes.  The implementation in Rocky's book is just a sample and can be modified to meet your needs.  I have done similar in past and it can work with no problems.

There is also no reason why this can't happen all in the same transaction, particularly with .Net 2.0 transaction support.  Just make sure your are not opening needless connections to the same database.  Prior to .Net 2.0 you would have to manually pass the transaction around to all the child objects.

You should be cognizant of the fact that you will take a performance hit for making more calls to the database.  One call that passes a large amount of data will perform better than many calls that each produce a subset.  However if your object hierarchies and transaction volume are reasonably sized you should be able to get away with it without the user noticing.

Thanks,

Kevin

Tray replied on Tuesday, February 13, 2007

Hi again Ash,

I'm glad that my suggestion was helpful.

I think a bit of qualification is required due to the amount of responses you have received.
I work with Windows Clients exclusivley, so if your application is web-based there may be some better suggestions or additions that are more in line with what you are trying to do.

It would be good if you could document the procedures that you are using for the root and child object, then we all could see what you are up against.

xal had a great idea - make sure you establish what data you need before grabbing everything from your db. There is no need to grab a root object and 500 child objects if the user is only going to pick one child object from the list of 500. Lazy loading is definately a consideration in this situation.

Remember to think of your user when building your apps - there the ones who have to use it. One thing I do my best to avoid is having the user wait ages for the data to be retrieved from the db (that pisses me right off, and I've seen heaps of professional in-house programs that load thousands of objects into a treeview - after about 30 seconds or more I get to see the treeview).

Please keep us up-to-date on your progress.

Regards
Tray

 

Ashraf Ali replied on Tuesday, February 13, 2007

Hi Tray,
you are right its a web app. thats why I want to make sure I dont load zillions of objects at one time or everytime I hit the database.
Give me a few days to post my progress as I have still lots of stuff to do on this app.
I will probably start new threads as I face problems,
Thanks for everyone's help
Ash

Ashraf Ali replied on Tuesday, February 13, 2007

Hi Folks,
Any one can get hold of some CodeSmith Templates which generates (or helps in generating) CSLA objects from Stored procs (not from Tables)?
I need these Templates for CSLA.NET 1.1 not 2.0

Thanks and Regards
Ash


Copyright (c) Marimer LLC