This project has moved. For the latest updates, please go here.

ParentLoad, LazyLoad and SelfLoad

Coordinator
Nov 9, 2010 at 9:14 PM
Edited Nov 9, 2010 at 9:18 PM

[Quoting Blarm Nov 09 at 4:16 PM]

Hi Tiago,

You also sent me a question regarding SelfLoad/ParentLoad which is connected with this posting.

It all depends on the Child Collection Properties

When you are doing a LazyLoad on any of the child collections then the whole object should not be loaded at once.
You may have 5 child collections and 3 are normal load and 2 are lazyload. Then you can load the 3 normal child collection with the parent using sql code that is generated. However the 2 lazyload child collections need to have LoadParameters defined and be loaded when first used.

With LazyLoad=true I do not see a difference between the LoadingScheme of ParentLoad or SelfLoad as the code generated is always something like:
Public ReadOnly Property RotNoteS As RotNoteS
    Get
        If Not FieldManager.FieldExists(RotNoteSProperty) Then
            If IsNew Then
                LoadProperty(RotNoteSProperty, RotNoteS.NewRotNoteS())
            Else
                LoadProperty(RotNoteSProperty, RotNoteS.GetRotNoteS(m_noteType, m_rotID))
            End If
        End If
        Return GetProperty(RotNoteSProperty)
    End Get
End Property


However for the child collections with LazyLoad=false then there needs to be both ParentLoad and SelfLoad options.
ParentLoad will include the SELECT for the load of the child collection in the generated sql and include the child collection in the FetchChildren:
e.g.:

dr.NextResult()
    Dim m_rotAirS As RotAirS = RotAirS.GetRotAirS(dr)
    LoadProperty(RotAirSProperty, m_rotAirS)



SelfLoad will NOT include the SELECT of the child collection in the sql generated and also the FetchChildren code it changed to:
   
    Dim m_rotNoteS As RotNoteS = RotNoteS.GetRotNoteS(m_noteType, m_rotID)
    LoadProperty(RotNoteSProperty, m_rotNoteS)


The reasons for using the LazyLoad=false AND LoadingScheme=SelfLoad is when it is not possible to automatically generate the correct sql code for the SELECT of the child collection. This can happen if there are none or multiple foreign keys on the child table and also if the the child is a view. Specifying SelfLoad stops the child SELECT sql being generated.

If you think it would be possible to specify and then use the LoadParameters to generate the sql code for the child SELECT in these cases then this would be very good and I do not think the SelfLoad would be needed.

The third options for LoadingScheme is None and that I suppose that is useful to stop the sql code and the class code being generated (although I do not think I have used this option).

I hope this helps,

Bill

[End of quote]

Coordinator
Nov 10, 2010 at 12:51 AM
Edited Nov 12, 2010 at 7:29 AM

Hi Bill,

Digging very hard I found http://cslagen.wiki-site.com/index.php/Business_Properties that says:

LazyLoad
If this is TRUE then the child object will not be loaded with data when the parent object fetches its data. It will only fetch its data when it is referenced for the first time.If this is FALSE then the child object will be populated with data by its parent object when the parent object fetches its own data.
 
LoadingScheme
If set to ParentLoad then the collection will be populated by the parent class. If set to SelfLoad the collection will load its own data. Finally if set to None then the collection will not be populated with data at all. 
 
ParentLoad is a regular mode of operation. The database query that fetches the parent data also takes care of fetching the child data.

The LazyLoad part is the one that is best known. It doesn't mention one has to create a get criteria for the collection but that isn't important since we it that from p. 281 of the VS2008 book. Besides, CslaGenFork's Object Relations Builder handles the criteria part for you. What it does is it defers child data fetching until the child data is refrenced for the first time. This also mean that the database query to fetch the child data it's the child responsability.

The interesting part is the SelfLoad. It looks a lot like LazyLoad because in LazyLoad the child also loads its own data. In both cases the child loads the data when the parent told it to, in both cases one has to create a get criteria for the collection. The difference is that in LazyLoad the parent defers the load until the property is referenced for the first time while in SelfLoad the parent tells the collection to load as soon as the parent is instantiated.

Things can get confusing as the UI layer will only talk to the parent and from the UI point of view it's not clear what's the difference (LazyLoad/SelfLoad). I guess the difference is whether the SQL query is issued by the parent object or by the collection method. So, in the ParentLoad/SelfLoad context, "Load" means what object issues the query.

Why is that a feature? Why is that feature important? Suppose the parent and the child come from different databases. It would be utterly complex to fetch the data in a single query/stored procedure and it's much more easy to have separate queries.

The point of "None" Loading Scheme is a bit obscure and it's not a most used or needed feature. The only pont I could find is to keep the child data fetching details out of the generated code. For .NET 4.0 we can generate an empty partial method and let the developer write the other method part, the one that actually does something.

Making sense of it all, one must ask a few questions:

  • Does the parent populate the child data?
  • If not, is the child data fetched on parent instantiation or defered until the child is referenced?
  • Does the generator know how to fetch the data?

 

Conclusion

There are 3 different factors to analyze the question how does the parent gets the child data (collection or not collection is just a detail):

  • WHO - is the child data fetched by the parent, at the same time the parent fetches its own data?
  • WHEN - is the child data fetched on parent instantiation or is this defered until child data reference?
  • KNOWLEDGE - does CslaGenFork knows how to fetch the data?

There are 5 different ways to combine these factors and generate the code for parent get child's data

If the data is fetched by the parent (WHO), there is only one possibility

1) ParentLoad
- parent fetches the child data (WHO)
- the data must be fetched all at the same time - on parent instantiation - so LazyLoad is implicitly false (WHEN)
- CslaGenFork must know how to fetch the child data, since there is only one SELECT to fetch all the data (KNOWLEDGE)

If the data is fetched by the child (WHO), there are 4 possible variations according to WHEN and KNOWLEDGE factors

2) SelfLoad
- CslaGenFork knows how to fetch the child data
- child data fetching occurs at parent instantiation time

3) SelfLoad and LazyLoad
- CslaGenFork knows how to fetch the child data
- child data fetching is defered until it's referenced

4) None
- CslaGenFork doesn't care about fetching the child data
- child data fetching occurs at parent instantiation time

5) None and LazyLoad
- CslaGenFork doesn't care about fetching the child data
- child data fetching is defered until it's referenced

Coordinator
Nov 12, 2010 at 12:41 AM

BTW, now you only need to specify LazyLoad once - on the child properties. The templates fetch the LazyLoad state there. Small change but big simplification for the user.

Developer
Nov 12, 2010 at 1:39 PM

Tiago,

I am having a think about this as I do not think it is quite correct.

I will get back to you later today.

Bill

Developer
Nov 12, 2010 at 3:47 PM

2) SelfLoad
- CslaGenFork knows how to fetch the child data 
- child data fetching occurs at parent instantiation time

3) SelfLoad and LazyLoad
- CslaGenFork knows how to fetch the child data
- child data fetching is defered until it's referenced

CslaGenFork knows how to fetch the child data - becuase it can use the LoadParameters specified to call the GetChildren(param1, param2, ..)
However it can not necessarily create the stored procedure for the GetChildren as the database may not give the relation between the child and parent (e.g. there is no foreighn key, the child is a view or the child is in a different database).
I think this would be the main reason for using SelfLoad and if this is what you meant then all is correct.

In CSLAGen the way that LoadParameters works is not very helpful. You have to choose the parameters from parent criteria, which means that you sometimes need a parent criteria that is not really necessary. You also have to have a criteria on the child collection which is correct as that is what is used to do the fetch. It would be better if you could choose the parameters from the child collection criteria as that is the criteria used for the fetch children.

 

Bill

Coordinator
Nov 13, 2010 at 2:51 AM
Edited Nov 13, 2010 at 8:19 AM

Hi Bill,

I'm not quite following you. I guess you are refering to what CslaGen did and I'm refering what CslaGenFork does. Of course the later is so new that only I have access to it :)

So I think the best way is to look at this as draft proposal.

When I first met CslaGen I found it very hard to understand. Duplicate SP generation, database settings al over the place, etc. Since I started this project, I became more and more aware of how it was intended to work and I think one of the biggest problems of CslaGen is the lack of complete and updated documentation (read User Manual). One thing I learned and have enforced on CslaGenFork: a Stored Procedure is generated only when, on a given criteria option the "Procedure" setting is true and there is a name for the procedure. A Stored Procedure is generated everytime this happens except when the object "Generate Stored Procedures" property is set to false. Although not generating the procedure, the procedure name is also needed if you are generating the DataPortal method. I believe you already know that all. I'm just clarifiyng so you can be sure I didn't change the rules.

The generation of the Stored Procedure for fetching the collection is dependent on the GetOptions.Procedure and GetOptions.ProcedureName of the collection criteria. The point here is all about program logic.

We can have a parent object that loads a SelfLoad collection on instantiation and that also does defered loading (aka LazyLoad) of another SelfLoad collection. This is no problem. I just tested it (and corrected the template) and saw it happening both in my console test application and on SQL Server Profiler. We can also mix ParentLoad with SelfLoad (on instantion and defered). Just tested the same way and again corrected the template :)

I must say the Stored Procedures that are generated for this mixed scenarios are wrong (a lot of work to do in this area) but since we are discussing program logic, that's besides the point. Let's just suppose SP generation was fixed.

As I see it, SelfLoad is useful in two scenarios:

  • purely by business reasons and the example that comes to my mind is the use of different databases - they just can't share the same query
  • you need/want to use LazyLoad (in this case, a variation aka LazyLoad)

You can also use SelfLoad as a work around for the present inabilty of CslaGenFork to generate the correct stored procedure for fetching the data in a single query. The alternative is to use ParentLoad, set the parent criteria GetOptions.Procedure to false and use your own hand coded Stored Procedure to fecth parent and child data in go.

On a different scenario the parent might not have the slightest idea how to fetch the child data. Suppose the child data is fecthed from a XML data file or a Web Service or some other data catalog CslaGen doesn't know how to handle. In this case, Loading Scheme None comes to rescue you. The FetchChildren method would became partial method so you could hand code your XML reader on the other part of the method. We are talking about an advanced scenario and in such a scenario, your child object must be set not to generate Factory Methods, nor Data Access Region nor Stored Procedures as it's impossible to generated them correctly. This is a change from my previous post, as in the present post there is no place for combining None with LazyLoad. Since we are using a scenario so out of CslaGen scope I'm not sure if we should find some way to allow for this combination.

In the light of this specifications, the use case you refer "the child is a view [of the same database?] so there is no way to generate the stored procedure correctly" can fit:

  • ParentLoad - if you intend to fetch the all the data in one go (faster than SelfLoad)
  • LazyLoad - if you want to defer child data fetching until the user needs it

If your parent and child data come from the same database, there is no need to use SelfLoad. The "don't generate SP" issue should be solved by setting the GetOptions.Procedure to false in the parent criteria for ParentLoad or in the child (or collection) criteria for the LazyLoad use case (assuming CslaGen can correctly generate the fetch parent SP).

A final note to say that up to this moment, all testing was done with ReadOnly objects and collections. As this may be a breaking template change, there won't be any commits before testing the other stereotypes.

Regards

Tiago Freitas Leal

Coordinator
Nov 13, 2010 at 6:37 PM
tiago wrote:

This is a change from my previous post, as in the present post there is no place for combining None with LazyLoad. Since we are using a scenario so out of CslaGen scope I'm not sure if we should find some way to allow for this combination.

The Loading Scheme / LazyLoad question involves code in two places

  • child property getter
  • DataPortal_Fetch

ParentLoad

The code is pretty straightforward:

  • child property getter - as normal as it could be
  • DataPortal_Fetch (with fetch parameters)
    • opens a database connection
    • sends an SQL command to fetch the parent and children data
    • uses a data reader to fecth the parent data and children data
    • closes the database connection

SelfLoad

The difference is on the DataPortal_Fetch

  • child property getter - as normal as it could be
  • DataPortal_Fetch (with fetch parameters)
    • opens a database connection
    • sends an SQL command to fetch the parent data
    • uses a data reader to fetch the parent data
    • closes the database connection
    • invokes a FetchChildren with the fetch parameters
    • the child Get factory method is invoked with the fetch parameters

LazyLoad

This is quite different from any of the above, although it shares part of the DataPortal_Fetch code of SelfLoad

  • child property getter
    • if the child property isn't yet populated with child data
      • the child Get factory method is invoked with the fetch parameters
  • DataPortal_Fetch (with fetch parameters)
    • opens a database connection
    • sends an SQL command to fetch the parent data
    • uses a data reader to fetch the parent data
    • closes the database connection

NoLoad (aka None)

This mode behaves just like SelfLoad except it generates a partial FetchChildren with the fetch parameters. This answers the scenario of data loaded from Oracle database, Web Services, XML files, you name it.

  • child property getter - as normal as it could be
  • DataPortal_Fetch (with fetch parameters)
    • opens a database connection
    • sends an SQL command to fetch the parent data
    • uses a data reader to fetch the parent data
    • closes the database connection
    • invokes a partial method FetchChildren with the fetch parameters
  • the implementation of the FetchChildren method must be done by the developer.

LazyNoLoad (aka None + LazyLoad)

The point under discussion is: should it also support a lazy load variation? LazyLoad depends on special code in the property getter that calls a standard Get factory method. This method isn't the responsability (isn't part) of the parent class. That's enough for discussion context.

This requisite makes a lot of sense: I have a child object/collection that uses customized code to fetch the data and I want to lazy load this object to improve user experience.

Does this child have a standard static Get factory method?

  • If the answer is NO, there is no way to respond to this requisite without resort to changes in child property popup. That's out of question for this moment and not a priority.
  • If the answer is YES, then why can't the parent invoke it when it needs to load the child data?

So the requisite makes sense but the proper way to solve it isn't at the parent level but at the child level. When I come to think of it, this whole None issue should be solved that way.

Coordinator
Nov 15, 2010 at 12:18 AM
tiago wrote:
  • NoLoad (aka None)

This mode behaves just like SelfLoad except it generates a partial FetchChildren with the fetch parameters. This answers the scenario of data loaded from Oracle database, Web Services, XML files, you name it.

  • child property getter - as normal as it could be
  • DataPortal_Fetch (with fetch parameters)
    • opens a database connection
    • sends an SQL command to fetch the parent data
    • uses a data reader to fetch the parent data
    • closes the database connection
    • invokes a partial method FetchChildren with the fetch parameters
  • the implementation of the FetchChildren method must be done by the developer.

LazyNoLoad (aka None + LazyLoad)

The point under discussion is: should it also support a lazy load variation? LazyLoad depends on special code in the property getter that calls a standard Get factory method. This method isn't the responsability (isn't part) of the parent class. That's enough for discussion context.

This requisite makes a lot of sense: I have a child object/collection that uses customized code to fetch the data and I want to lazy load this object to improve user experience.

Does this child have a standard static Get factory method?

  • If the answer is NO, there is no way to respond to this requisite without resort to changes in child property popup. That's out of question for this moment and not a priority.
  • If the answer is YES, then why can't the parent invoke it when it needs to load the child data?

So the requisite makes sense but the proper way to solve it isn't at the parent level but at the child level. When I come to think of it, this whole None issue should be solved that way.

No one could explain the use for the None option and up to this moment I found none. On change set #4388 this option was temporarily deprecated - ChildValidate doesn allow you to use it. If there is some use to it after all, it will be allowed again and given its to-be-defined use.

Developer
Nov 15, 2010 at 12:05 PM
Edited Nov 15, 2010 at 12:48 PM

Tiago,

I think that we are both describing the same things.
However, I am looking at it from a parent with several children.
Each of the children may have different combinations of LazyLoad/LoadingScheme (ignoring None for the time being)

  • Parent DataPortal_Fetch
    • opens a database connection
    • sends an SQL command to fetch the parent and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • uses a data reader to fetch the parent data and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • invokes FetchChildren
      • for all children with LazyLoad=false and LoadingScheme=ParentLoad
        • the child is loaded from the data reader
      • for all children with LazyLoad=false and LoadingScheme=SelfLoad
        • the child Get factory method is invoked with the LoadParameters parameters
    • closes the database connection
  • Child Property Getter (CPG)
    • if LazyLoad=false then the CPG is as normal as it could be
    • if LazyLoad=true then
      • if the child property isn't yet populated with child data
        • if LoadingScheme=ParentLoad the child Get factory method is invoked with the fetch parameters
        • if LoadingScheme=SelfLoad the child Get factory method is invoked with the LoadParameters parameters

As you can see when LoadingScheme=SelfLoad then the LoadParameters are used.
Currently in CSLAGen when you select the LoadParameters they are chosen from a list that shows the Parent Criteria.
This is incorrect as the list should show the Child Criteria so that they link up with the child Get factory method.
The way around this in CSLAGen is to set up an extra Parent Criteria that is the same as the Child Get Criteria.
For CSLAGenFork it would be nice if this inconsistency was fixed.

I would also like to see the way that the Parent DataPortal_Fetch handles the children changed to:

  • Parent DataPortal_Fetch
    • opens a database connection
    • sends an SQL command to fetch the parent and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • uses a data reader to fetch the parent data and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • invokes FetchChildren1
      • for all children with LazyLoad=false and LoadingScheme=ParentLoad
        • the child is loaded from the data reader
    • closes the database connection
    • invokes FetchChildren2
      • for all children with LazyLoad=false and LoadingScheme=SelfLoad
        • the child Get factory method is invoked with the LoadParameters parameters

Splitting the FetcChildren into 2 parts would mean that the databse connection was closed before the children with LazyLoad=false and LoadingScheme=SelfLoad were fetched.
This would allow a different database to be open without the complications of EnterpriseServices.

Also I don't think you need to spend and time in getting the stored procedures to generate correctly when LoadingScheme=SelfLoad as the reason for using LoadingScheme=SelfLoad will probably be because the sql code needs to be manually set up.

Bill

Coordinator
Nov 16, 2010 at 1:08 AM
Edited Nov 16, 2010 at 1:23 AM
Blarm wrote:
  • Parent DataPortal_Fetch
    • sends an SQL command to fetch the parent and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • uses a data reader to fetch the parent data and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
  • Child Property Getter (CPG)
    • if LazyLoad=true then
      • if the child property isn't yet populated with child data
        • if LoadingScheme=ParentLoad the child Get factory method is invoked with the fetch parameters
        • if LoadingScheme=SelfLoad the child Get factory method is invoked with the LoadParameters parameters

I feel confused. ParentLoad means the parent goes and fetches the data and then transfers the data to the child (or transfers a data reader to the child). If the child takes care of fetching it's own data, than it's not parent load, it's child load (SelfLoad in CslaGen lingo). Anyway in ParentLoad the parent load parameters are never transfered to the child or used by the child because the child just handles a data reader.

On the other hand, on SelfLoad, the parent load parameters are transferd to the child but aren't used directly to load anything at all. The child load parameters are used to fetch the data. The expression "load parameters" means the DB Bind Columns that are used to select the child collection. Of course the value used in the SELECT statment come from a parent object. Are you saying there might be some use cases where there is a mismatch between the parent load parameters and the way the child collection uses them? If the parent load parameter is a user name and the child load parameter is a user ID, there will be a type mismatch. It's up to you to make sure that this doesn't happen.

 

Blarm wrote:

As you can see when LoadingScheme=SelfLoad then the LoadParameters are used.
Currently in CSLAGen when you select the LoadParameters they are chosen from a list that shows the Parent Criteria.
This is incorrect as the list should show the Child Criteria so that they link up with the child Get factory method.
The way around this in CSLAGen is to set up an extra Parent Criteria that is the same as the Child Get Criteria.
For CSLAGenFork it would be nice if this inconsistency was fixed.

I'm not following you. My ParentLoad sample has only one criteria specified at the parent level. No need or use for any other criteria. When I use SelfLoad I need to specify a criteria for the child collection. Are you saying that SelfLoad is also useful for use cases where there is the need to have a different load parameters for the child? In fact, when I use SelfLoad the generated SP are correct... Maybe you're right!

Anyway, can you give us a use case to illustrate the issue?

My use case is a bit like Outlook

Parent
- Inbox object - this is a simplified user object with a property UserID
Child Collections
- SentMessages - this a collection of messages where SenderID = UserID
- ReceivedMessages - this a collection of messages where ReceiverID = UserID

The parent LoadParameter is UserID
The SentMessages LoadParameter is SenderID
The ReceivedMessages LoadParameter is ReceiverID

On SelfLoad,
- the parent invokes the child factory Get with parameter UserID
- the child collections use this parameter as SenderID or ReceiverID

As you casn guess, this behaves just nicely and everything is loaded the right way.

 

Blarm wrote:

Also I don't think you need to spend and time in getting the stored procedures to generate correctly when LoadingScheme=SelfLoad as the reason for using LoadingScheme=SelfLoad will probably be because the sql code needs to be manually set up.

 If you don't need to use a different database connection (or use different load parameters?) then you don't need SelfLoad. Just hand type the stored procedure and use ParentLoad :)

Of all CslaGen parts, SprocTemplateHelper.cs and SP generation is the weakest part. The code it's a real mess and one of these days I'll throw it away and write it from scratch.

The point about wrong SP generation is that I don't want to use SP forever. I want CslaGenFork to generate both SP and parametrized queries embedded in program code. This code is harder to correct than plain SP and can't have wrong statements. Maybe the CslaGenFork hasn't got the all the information the generator needs to fix SP generation. The example of using views - that have no constraints or FK - is a good example. The UI must provide some way for the user to input the information the generator can't find. I added a new property FKConstraint that should help the generator deciding how to build the query and indeed it does in some situations, The problem is that SprocTemplateHelper.cs is a mess and I only managed to change/enhance it here and there. Sometimes it looks like different parts of CslaGen were made by different people with totally different ways of programming.

I think we might have made some progress and found a new use case for using SelfLoad and not have to hand code the SP.

Regards

Tiago Freitas Leal

Coordinator
Nov 16, 2010 at 1:21 AM
Blarm wrote:

I would also like to see the way that the Parent DataPortal_Fetch handles the children changed to:

  • Parent DataPortal_Fetch
    • opens a database connection
    • sends an SQL command to fetch the parent and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • uses a data reader to fetch the parent data and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • invokes FetchChildren1
      • for all children with LazyLoad=false and LoadingScheme=ParentLoad
        • the child is loaded from the data reader
    • closes the database connection
    • invokes FetchChildren2
      • for all children with LazyLoad=false and LoadingScheme=SelfLoad
        • the child Get factory method is invoked with the LoadParameters parameters

Splitting the FetcChildren into 2 parts would mean that the databse connection was closed before the children with LazyLoad=false and LoadingScheme=SelfLoad were fetched.
This would allow a different database to be open without the complications of EnterpriseServices.

Sorry, I missed the first quoted line and thought you were describing the present behaviour of the last commit. I even though "Gosh this guy made his tests very quickly. The new code was commited just a few hours ago... Then again, it seems no one got it... So how did he get it?..." etc. 

It's done and tested as you can see in the work item #306

Coordinator
Nov 16, 2010 at 1:42 AM
Edited Nov 16, 2010 at 1:43 AM

I like the fact that ParentLoad fetches everything from the DB in just one command/SP. I don't like the fact that the generated SP is wrong but with just the parent criteria, there is no way to get the correct SP code.

I like the fact that SelfLoad generates the correct SP. I don't like the idea of having to fetch the data in more than one command, except when each command uses a different database.

Maybe we can merge both worlds and have a special mode ParentMergeLoad:

  • you must have a criteria for the parent and a criteria for each child (like SelfLoad)
  • CslaGenFork generates only one SP (like ParentLoad, but a correct one)
  • CslaGenFork generates ParentLoad code (since we have only one SP, that's the correct code)

Why a new mode? Because you might need to use the proper SelfLoad mode when parent and child data come from different databases.

Maybe we don't need a new mode and just need to specify the child criteria using ParentLoad in order to get the SP right... (I tryed it but it doesn't generate the SP correctly)

Developer
Nov 16, 2010 at 12:41 PM
tiago wrote:
Blarm wrote:
  • Parent DataPortal_Fetch
    • sends an SQL command to fetch the parent and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
    • uses a data reader to fetch the parent data and children data for all children with LazyLoad=false and LoadingScheme=ParentLoad
  • Child Property Getter (CPG)
    • if LazyLoad=true then
      • if the child property isn't yet populated with child data
        • if LoadingScheme=ParentLoad the child Get factory method is invoked with the fetch parameters
        • if LoadingScheme=SelfLoad the child Get factory method is invoked with the LoadParameters parameters

I feel confused. ParentLoad means the parent goes and fetches the data and then transfers the data to the child (or transfers a data reader to the child). If the child takes care of fetching it's own data, than it's not parent load, it's child load (SelfLoad in CslaGen lingo). Anyway in ParentLoad the parent load parameters are never transfered to the child or used by the child because the child just handles a data reader.

On the other hand, on SelfLoad, the parent load parameters are transferd to the child but aren't used directly to load anything at all. The child load parameters are used to fetch the data. The expression "load parameters" means the DB Bind Columns that are used to select the child collection. Of course the value used in the SELECT statment come from a parent object. Are you saying there might be some use cases where there is a mismatch between the parent load parameters and the way the child collection uses them? If the parent load parameter is a user name and the child load parameter is a user ID, there will be a type mismatch. It's up to you to make sure that this doesn't happen.

 

If we go back to the original in this post:

tiago wrote:

Hi Bill,

Digging very hard I found http://cslagen.wiki-site.com/index.php/Business_Properties that says:

LazyLoad
If this is TRUE then the child object will not be loaded with data when the parent object fetches its data. It will only fetch its data when it is referenced for the first time.If this is FALSE then the child object will be populated with data by its parent object when the parent object fetches its own data.
 
LoadingScheme
If set to ParentLoad then the collection will be populated by the parent class. If set to SelfLoad the collection will load its own data. Finally if set to None then the collection will not be populated with data at all. 
 
ParentLoad is a regular mode of operation. The database query that fetches the parent data also takes care of fetching the child data.


From this you can see that it is LazyLoad that defines whether the child data is fetched when the parent is fetched (LazyLoad=false then fetch at the same time as the parent, LazyLoad=true then defer fetch until child is referenced). For LoadingScheme=ParentLoad the child is populated by code in the parent class by transferring an already populated data reader to the child. LoadingScheme=SelfLoad means that the child is populated by code in its own class using the Get factory method

 

  • LazyLoad=false - Fetch parent and Child at the same time
    • LoadingScheme=ParentLoad - the child will be fetched in the parent class by being included in the parent fetch stored procedure and the child loaded via a datareader
    • LoadingScheme=SelfLoad - the child will be fetched in the parent class using a call to the child Get factory method using LoadParameters
    • Child Property Getter - as normal as it could be
  • LazyLoad=true - Child is fetched when first referenced in the Child Property Getter (CPG) and so there is no code in the parent class fetch
    • CPG - Child already loaded
      • CPG as normal as it could be
    • CPG - Child not loaded
      • LoadingScheme=ParentLoad - child Get factory method is invoked with the parent criteria paramaters
      • LoadingScheme=SelfLoad - child Get factory method is invoked with the LoadParamaters

Stored Procedure (SP) Generation
From what I remember the store procedure (SP) generation uses foreign key relationship (FK) to generate the correct code for the parent->child SELECT

  • LazyLoad=false - Fetch parent and Child at the same time
    • LoadingScheme=ParentLoad - Assuming that you have set up a FK between the parent and child then the SP to load the parent and child together will generate correctly
    • LoadingScheme=SelfLoad - I can not see how a SP can be generated correctly as the LoadParamaters will only be used to pass through to the hand coded SP.
  • LazyLoad=true - Child is fetched when first referenced in the Child Property Getter (CPG) and so there is no code in the parent class fetch
    • LoadingScheme=ParentLoad - Assuming that you have set up a FK between the parent and child a get SP to load the child independently will generate correctly and will use the parent criteria paramaters
    • LoadingScheme=SelfLoad - I can not see how a SP can be generated correctly as the LoadParamaters will only be used to pass through to the hand coded SP.

When do I use the different options

  • LazyLoad=false, LoadingScheme=ParentLoad - In an ideal world I would always use this as that would get all the data together and be as efficient as possible. That's how it is in over 90% of the cases I have
  • LazyLoad=false, LoadingScheme=SelfLoad - I want the child loaded when the parent is loaded, but:
    • the parent criteria does not give me the access to the child that I require (e.g. I only want to see the child object with a particular status- WHERE child.ParentID = @ParentID AND child.Status = @Status) so I set up the LoadParamaters to pass through to the child Fetch and hand code the SP to reference the LoadParamaters
    • the parent has no relationship set up in the database with the child (e.g. child is a view, or child is in a differnet database) and I set up the LoadParamaters to pass through to the child Fetch and hand code the SP to reference the LoadParamaters
  • LazyLoad=true, LoadingScheme=ParentLoad - The child has a FK with the parent, AND the collection is very large and the UI needs to see the parent information as soon as possible and the child info may not be used unless the user selects it from the UI. The parent criteria can be used to fetch the data.
  • LazyLoad=true, LoadingScheme=SelfLoad - As above, the parent criteria does not give me the access that I require or the child does not have a FK relationship with the parent AND the collection is very large and the UI needs to see the parent information as soon as possible and the child info may not be used unless the user selects it from the UI so I set up the LoadParamaters to pass through to the child Fetch and hand code the SP to reference the LoadParamaters

Bill

Coordinator
Nov 16, 2010 at 1:54 PM

Hi Bill,

Sorry I just can't follow you.

Let's get back to the start and clear some basic concepts and trying to keep it simple, one thing at a time, keeping the load parameters issue out of the way.

FETCH METHOD - The method that runs an SQL SELECT statement that returns a result set with data. This result set can be read using a single data reader.
WHERE - The parent or child location of the FETCH METHOD for child data
WHEN - The moment the FETCH METHOD for child data runs. This can be at parent instantiation or child data reference.

1) If I have a single FETCH METHOD for parent and child data, it most be run in the parent, and on parent instantiation.

2) If I have different FETCH METHODs for parent and child data, I can run the child FETCH METHOD in two different WHERE: the parent or the child.

3) If I have different FETCH METHODs for parent and child data, I can run the child FETCH METHOD on two different WHEN: parent instantiation or child data reference.

I really fail to see how I can have a single method and fecth the resulting data sets in different locations or moments.

Developer
Nov 16, 2010 at 6:38 PM

FETCH METHOD - The method that runs an SQL SELECT statement that returns a result set with data. This result set can be read using a single data reader.
WHERE - The parent or child location of the FETCH METHOD for child data
WHEN - The moment the FETCH METHOD for child data runs. This can be at parent instantiation or child data reference.

1) If I have a single FETCH METHOD for parent and child data, it most be run in the parent, and on parent instantiation.
    Yes - this is LazyLoad=False, LoadingScheme=ParentLoad

2) If I have different FETCH METHODs for parent and child data, I can run the child FETCH METHOD in two different WHERE: the parent or the child.
     If there are different FETCH METHODs then the parent method code should be in the parent class (WHERE) and child method code in the child class (WHERE) and LoadingScheme=SelfLoad for the child.

3) If I have different FETCH METHODs for parent and child data, I can call the child FETCH METHOD on two different WHEN: parent instantiation or child data reference.
     Yes - parent instantiation : LazyLoad=false, LoadingScheme=SelfLoad for the child, child data reference : LazyLoad=true, LoadingScheme=SelfLoad for the child

I really fail to see how I can have a single method and fecth the resulting data sets in different locations or moments.
     I appologise for confusing you here. What I mean is that a single parent may have several children types/collections and each individual child type/collection may require a different loading mechanism.
     So if a parent had 3 children collections, of which child1 and child2 can be fetched with the parent and child3 that could not, then there would be 2 stored procedures: first stored proc containing the SELECTs for the parent and child1 and child2, and a 2nd stored proc for the child3 SELECT.

Coordinator
Nov 16, 2010 at 11:31 PM

Agree and - as I told you before - done