Lazy loading fetch from DB even if IsNew is set

Posts   
 
    
lubo278
User
Posts: 32
Joined: 10-Apr-2007
# Posted on: 25-Feb-2010 15:43:43   

Hi,

I am really confused as I consider myself an advanced LLBL user and this is really fundamental thing.

I tried this code

new FlightEntity().FlightSegment

FlightSegment is related table to FlightEntity (so it is of type FlightSegmentCollection).

I would suspect, that this will not go to database for any data (why should it? since new FlightEntity().IsNew == true?). But if I debug database output I can see sql query

    Query: SELECT ... WHERE ( ( ...[FlightSegment].[IdFlight] = @IdFlight1))
    Parameter: @IdFlight1 : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 0.

I could set (although private) AlreadyFetchetFlight property, but is this a solution?

Maybe I have something wrong in my project (as it is really old) but I can't see any reason for this.


LLBL version: 2.5.7.1219 DB: MS SQL 2005

lubo278
User
Posts: 32
Joined: 10-Apr-2007
# Posted on: 25-Feb-2010 16:15:59   

I tried it with some newer version 2.6.9.807, the behavior is the same.

I think that expected behavior would be that if PK of table is null, this lazy loading should not occur. Am I missing something? simple_smile

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 25-Feb-2010 21:27:02   

Did you try regenerating with the new version, or just running against the new runtime libs ?

Matt

lubo278
User
Posts: 32
Joined: 10-Apr-2007
# Posted on: 26-Feb-2010 08:17:46   

I tried totally different project and different DB.

If I look into generated code in EntityBase class and I can see this

        public virtual XMLogies.Online.LLBL.CollectionClasses.FlightSegmentCollection GetMultiFlightSegment(bool forceFetch, IEntityFactory entityFactoryToUse, IPredicateExpression filter)
        {
            if( ( !_alreadyFetchedFlightSegment || forceFetch || _alwaysFetchFlightSegment) && !base.IsSerializing && !base.IsDeserializing && !base.InDesignMode)
            {

...

                _flightSegment.GetMultiManyToOne(this, filter);
                _flightSegment.SuppressClearInGetMulti=false;
                _alreadyFetchedFlightSegment = true;
            }
            return _flightSegment;
        }

so there is basically no other condition than _alreadyFetchedFlightSegment (by default false).

Walaa avatar
Walaa
Support Team
Posts: 14994
Joined: 21-Aug-2005
# Posted on: 26-Feb-2010 08:52:24   

Your request might be valid, so we will investigate it in depth.

But I think there are some more use cases behind this, as for instance you can use a new entity and set it's PK (not in the CTor), then witout fetching it, you can fetch its related entities, either by accessing the corresponding property or by calling the correct GetMultixxx() method.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 26-Feb-2010 09:48:09   

Walaa described the use-case why we didn't implement this. It's been requested before but it broke existing software so we didn't do it.

Lazy loading is a tool like any other: use it when needed, and avoid it when you don't need it. As it happens without noticing, it might be lazy loading is causing a lot of performance hits (the SELECT N+1 problem), so keep in mind that lazy loading should be used with care like any other tool in our toolbox.

Frans Bouma | Lead developer LLBLGen Pro
lubo278
User
Posts: 32
Joined: 10-Apr-2007
# Posted on: 26-Feb-2010 10:02:00   

Yes, I understand that lazy loading must be taken with care (basically prefetch path always solved all performance issues for me). But could you help me with this scenario - I want to create some bigger structure of related entities and collections in memory and then save it to database. In my projects it was always common issue (i.e. parsing some XML, then saving in transaction after all data have been parsed and minimalizing transaction lock time).

The use case that Walaa described is of course possible, but I think less probable than "my" scenario. Also there is no other way to make "my" scenario.

I will try to make some suggestion of changed templates and send it to review here.

lubo278
User
Posts: 32
Joined: 10-Apr-2007
# Posted on: 26-Feb-2010 13:23:52   

I extended EntityBase template (this is sample from FlightEntity mentioned above)

public virtual XMLogies.Online.LLBL.CollectionClasses.FlightSegmentCollection GetMultiFlightSegment(bool forceFetch, IEntityFactory entityFactoryToUse, IPredicateExpression filter)
        {
            if( ( !_alreadyFetchedFlightSegment || forceFetch || _alwaysFetchFlightSegment) && !base.IsSerializing && !base.IsDeserializing && !base.InDesignMode)
            {
                // CHANGE START HERE - check if this entity is initialized
                foreach (IEntityField field in Fields)
                {
                    if (field.IsPrimaryKey && this.CheckIfCurrentFieldValueIsNull(field.FieldIndex))
                    {
                        return _flightSegment;
                    }
                }
                // CHANGE END HERE


                if(base.ParticipatesInTransaction)
                {
                    if(!_flightSegment.ParticipatesInTransaction)
                    {
                        base.Transaction.Add(_flightSegment);
                    }
                }
                _flightSegment.SuppressClearInGetMulti=!forceFetch;
                if(entityFactoryToUse!=null)
                {
                    _flightSegment.EntityFactoryToUse = entityFactoryToUse;
                }
                _flightSegment.GetMultiManyToOne(this, filter);
                _flightSegment.SuppressClearInGetMulti=false;
                _alreadyFetchedFlightSegment = true;
            }
            return _flightSegment;
        }

I think this should improve performance (it really did in my project in few profiling sessions) and does not have any side effect.

Sorry to bother, but I still think this is major issue of Self Servicing scenario.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 28-Feb-2010 11:28:07   

we'll look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 01-Mar-2010 10:13:48   

It's not always pk fields, it's also fk fields which are involved (m:1 relationships). See my reply here: http://www.llblgen.com/tinyforum/GotoMessage.aspx?MessageID=87864&ThreadID=15753

We have logged this issue for a future update of v3.x, it's currently planned for the RTL revision update in the 3.x timeframe where we'll check for lazy loading based on field values.

Frans Bouma | Lead developer LLBLGen Pro