Lazy load or not lazy load on demand

Lazy load or not lazy load on demand

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


hramos360 posted on Monday, July 11, 2011

Is there a better way to the following:

I'm trying to give the UI the option of lazy loading a child collection or not lazy loading.
The I am having is the RegisterProperty method can only occur statically, otherwise, I get
the  "Cannot register property ... after containing type (...) has been instantiated" error.

This leaves me the option of defining two static properties, call it PhonesProperty and LazyPhonesProperty
with the appropriate relationship type options set


For example, say I have a Person class derived from BusinessBase.
The person has a collection of phones for which I create a Phones property.
I keep simple LazyLoadPhones flag, pass as a criteria member to the data portal which
sets it value when reading the Phones property as follows:

     private static readonly PropertyInfo<Phones> PhonesProperty = RegisterProperty<Phones>(c => c.Phones, RelationshipTypes.Child);
        private static readonly PropertyInfo<Phones> LazyPhonesProperty = RegisterProperty<Phones>(c => c.Phones, RelationshipTypes.Child | RelationshipTypes.LazyLoad);
        /// <summary>
        /// Returns the child phone collection of this business object instance. 
        /// </summary>
        public Phones Phones
        {
            get
            {
                if (LazyLoadPhones)
                {
                    if (!FieldManager.FieldExists(LazyPhonesProperty))
                    {
                        var creator = DataPortal.Fetch<PhoneListCreator>();
                        Phones = creator.Result;
                    }
                    return ReadProperty(LazyPhonesProperty);
                }
                else
                    return ReadProperty(PhonesProperty);
            }
            private set
            {
                if (LazyLoadPhones)
                    LoadProperty(LazyPhonesProperty, value);
                else
                    LoadProperty(PhonesProperty, value);
            }
        }


I'd rather not go in this direction, but I want to give the UI the flexibility to lazy loading or not.

Any ideas?

Marjon1 replied on Monday, July 11, 2011

The only thing that should change if you don't want to lazy load is at the time of creating the instance of Person, so that the DataPortal.Fetch() method can load the PhonesProperty.

Then your property can still do it's check for FieldManager.FieldExists() which if it has already been loaded will be true, otherwise it will do a lazy-load as you would want it to. Obviously, if you want to lazy-load multiple properties then your factory method may become a bit more complicated, but I would assume you would lazy-load all or none.

hramos360 replied on Tuesday, July 12, 2011

So you mean, that my assumption is correct? Namely, if I want to support lazy load or not lazy load on a child at the same time, I have to define two PropertyInfo<T> properties?  Any have an example of this?

 

Thanks

 

 

hramos360 replied on Tuesday, July 12, 2011

The other issue I ran into is that you can only register a property of a certain type one time, so the following does not work:

 

private static readonly PropertyInfo<Phones> PhonesProperty = RegisterProperty<Phones>(c => c.Phones, RelationshipTypes.Child);

 

 

 

private static readonly PropertyInfo<Phones> LazyPhonesProperty = RegisterProperty<Phones>(c => c.Phones, RelationshipTypes.Child | RelationshipTypes.LazyLoad);

 

  

 It throws a Cannot register property Phones, a PropertyInfo with the same name already exist.

 

So it looks like I will have to create two unique properties if I want to simultaneaously support lazy loading or not lazy loading of a child collection.

Any thoughts?

 

tmg4340 replied on Tuesday, July 12, 2011

Let's back up a bit.  It sounds like you want to make it possible for your UI to somehow decide at runtime whether it should lazy-load properties or not.  Why do you need to do this?  A more detailed explanation of the issue may help us give you a solution, because I'm honestly not sure why you'd need to do this...

- Scott

hramos360 replied on Tuesday, July 12, 2011

This is correct Scott.  The reason I want to do this is because there might be different UI screens that decide how they want children loaded.  In some cases, they may want to lazy load children, in other cases they may want to load a particular child when fetching the parent.  My feeling is why should it be one or the other. 

 

tmg4340 replied on Tuesday, July 12, 2011

And that's fine - but why does that decision need to be made at runtime?  Can't the UI designer decide that when they're building the screen?

If that's what you're talking about, remember that I'm pretty sure all the "LazyLoad" relationship type does is tell CSLA to throw an exception if you try to read the property before you set it.  Given that, I don't see why you need two property declarations - declare it once (with a LazyLoad enumeration), build your factory methods to allow your UI creators to say whether you want to lazy-load the child(ren) or not, and go from there.  Yes, it makes your BO's more complicated, but not terribly so.  As Marjon said, most of the complexity resides in your Fetch method and DAL code.

Ultimately, I don't think you're going to see a ton of gain from this concept anyway, as I don't think the flexibility is going to gain you all that much given the coding overhead.  But that's purely MHO.  I suppose a lot depends on how much your BO's are re-used across screens.

HTH

- Scott

hramos360 replied on Tuesday, July 12, 2011

Thanks for you insight.  I think you are correct.  I'll just stick with LazyLoading as the child properties will be fetched when needed. 

 

Copyright (c) Marimer LLC