Entity: OnInitialized being called multiple times when fetching Async

Posts   
 
    
TopDog74
User
Posts: 40
Joined: 27-Apr-2012
# Posted on: 10-Jul-2015 16:43:01   

Hi,

While writing some custom validation code for my entities i discovered that when i was fetching the Entity asynchronously the 'OnInitialized' method is getting called multiple times. Is this the expected behaviour?

Is there a more suitable method i can override or use to initialize my validation rules?

Code Example below to explain what's happening.


        //My generated Entity Code Sample
        //this method gets called multiple times when getting the entity Async
        protected override void OnInitialized()
        {
            base.OnInitialized();

            CreateValidationRules();
        }

//Querying code examples
using (DataAccessAdapter adapter = new DataAccessAdapter())
            {
                var response = new VesselEntity(); //On initialized happens once here
                response.VesId = vesId;
                adapter.FetchEntity(response);

                var response = await adapter.FetchFirstAsync(query, CancellationToken.None); //On initialized happens multiple times if i use this approach instead
                return response;
            }


Thanks, Iain

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Jul-2015 10:04:45   

TopDog74 wrote:

While writing some custom validation code for my entities i discovered that when i was fetching the Entity asynchronously the 'OnInitialized' method is getting called multiple times. Is this the expected behaviour?

I reproduced it, using latest v4.2:

[TestMethod]
public void TestMethod1()
{
    using (DataAccessAdapter adapter = new DataAccessAdapter())
    {
        var query = new QueryFactory().Customer;
        var customer = GetCustomer();
    }
}

private async Task<CustomerEntity> GetCustomer()
{
    using (DataAccessAdapter adapter = new DataAccessAdapter())
    {
        var query = new QueryFactory().Customer;
        var response = await adapter.FetchFirstAsync(query, CancellationToken.None); 
        return response;
    }           
}

Then OnInitialized is called 4 times. I think is because the way the constructor is used accross the all the fetch operation. I really don't know whether this is expected. I will investigate further.

TopDog74 wrote:

Is there a more suitable method i can override or use to initialize my validation rules?

I think that you could just check whether the validation rules exists already, or you have to create them.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-Jul-2015 10:59:19   

The method by itself could get called multiple times, as the framework sometimes creates dummy instances, as some data isn't available to the inner core of the runtime other than through instances. Creating these instances is almost free (it's very fast, so it's not like this slows down performance), however it indeed has the side effect of having these methods getting called too. It's not the same entity object however. If you check this.ObjectID every time your OnInitialized method is called, it's a different Guid each time. The first one is for the entity factory factory which is run once. These dummy instances are thrown away after they've been used.

To be sure, you can check whether the initialization already has taken place, e.g. when you're setting things up for all instances of a given type. If you're using validation rules, another way to do this is by using a validator instance which is injected with dependency injection. This creates bigger decoupling as you then don't need to add code to the generated class assembly through partial classes.

So the method is called once per entity class instance, but for fetching 1 entity it can be called multiple times, once for each entity class instance that's been created along the way.

It's a side effect of our distributed system internally (no central context/session), where one object needs information to decide something and creates a dummy to do so, before proceeding. E.g. to produce a query it creates a dummy (for the fields and other info), to fetch the query it uses a different object, namely one created from a factory as the query might return more than 1 element (it doesn't know that at that point, nor does it care). When initializing the system it builds a factory cache which too creates dummies (once).

Frans Bouma | Lead developer LLBLGen Pro