Reuse adapter instance?

Posts   
 
    
mdbruning
User
Posts: 18
Joined: 10-Mar-2008
# Posted on: 15-Feb-2016 10:22:22   

Hi all,

I've been working with LLBLGen for quite some time now, but that has always been using Self Servicing. We're now moving onto Adapter and I have a question about that.

The question is whether it is possible and whether it's the best practice to reuse a DataAccessAdapter instance within a Validator class. We have a separate assembly which injects the validator classes using Dependency Injection.

In a separate assembly, we have a repository class which creates the DataAccessAdapter instance and calls the DeleteEntity method on the DataAccessAdapter. After calling the DeleteEntity method, the ValidateEntityBeforeDelete method is called in the validator class. Here I'd like to fetch some more entities from the database and I was wondering whether I could reuse the DataAccessAdapter that was initially used to delete the entity.

Is that good practice? And if so, how can I get a reference to that DataAccessAdapter instance?

Perhaps it's a newbie question, but hopefully someone can give me an answer of how to deal with 'nested' opening of database connections.

Thanks in advance!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Feb-2016 10:56:53   

re-using an adapter is fine, as long as it's on the same thread. So storing an adapter instance in a static variable is not what you should do (you don't gain anything with it either, instantiating an adapter is very fast).

About your question: what are you going to do with the fetched entities in the validation method? So what is the purpose of them? It might be there is a better way to do it without fetching data in a validator, as the validator is meant to validate, not fetch data.

Frans Bouma | Lead developer LLBLGen Pro
mdbruning
User
Posts: 18
Joined: 10-Mar-2008
# Posted on: 15-Feb-2016 11:15:15   

What we have done in the past - and this might be incorrect usage of the validator classes - is using the ValidateEntityBeforeSave and ValidateEntityBeforeDelete to apply certain logic when an entity is saved or deleted. In this way, we know for sure that this logic is executed for each entity using the dependency injection mechanism, as we've set the dependency injection for types of IEntity2 (see code below)

    [DependencyInjectionInfo(typeof(IEntity2), "Validator", ContextType = DependencyInjectionContextType.Singleton)]
    public class GeneralValidator : ValidatorBase
    {
        public override void ValidateEntityBeforeSave(IEntityCore involvedEntity)
        {
            base.ValidateEntityBeforeSave(involvedEntity);
        }

        public override void ValidateEntityBeforeDelete(IEntityCore involvedEntity)
        {
            IEntity2 useableEntity = involvedEntity as IEntity2;
            if (useableEntity != null)
            {
                using (DataAccessAdapter adapter = new DataAccessAdapter())
                {
                        // Fetching other entities and doing other stuff
                }
            }

            base.ValidateEntityBeforeDelete(involvedEntity);
        }
    }

In this case, we have implemented a mechanism to apply referential constraints which is executed on each entity delete using the validator code above. This might be a complete misusage of the validator classes but this has always worked for us when working with Self Servicing as we didnt had the DataAccessAdapter instances then. When we switched to adapter we did get these DataAccessAdapter instances and therefore I was wondering whether it was possible to reuse them.

Especially in this case where it felt a bit unneccessary to open different DataAccessAdapter instances in a nested way in the validator class. I was hoping for a property on the entity with a reference to the DataAccessAdapter, but couldn't find any.

So what you're saying is just keep on opening these DataAccessAdapter instances, apart from the fact tat we're incorrectly using the validators?

And what would be the better place to call this referential constraint logic from?

Thanks again.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 16-Feb-2016 05:27:05   

If you are checking for related entities before deleting the entity, in order to cancel the deletion if they exist. I'd say leave it to the database, if these referential constraints have been set there. All you need to do is catch the exception thrown back from the database and report it to the user. In some of these relation you might want to just delete the related entities as well, and thus a Cascade delete might come in handy.

From a performance point of view, this is much better, than querying the database on each delete for related entities on different tables.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 16-Feb-2016 10:31:09   

Indeed, cascading actions (delete / null set) might be a better option. If you check by loading entities, then delete them, in the mean time some other user might have done something to the entities you just checked.

Additionally, using DeleteEntitiesDirectly, you can delete entities with where clauses which refer to other entities, that also might be an option.

Frans Bouma | Lead developer LLBLGen Pro
Pilo
User
Posts: 13
Joined: 07-Oct-2014
# Posted on: 19-Mar-2018 14:10:19   

This situation applies to my project as well. Sometimes the validators need to check for uniqueness or something else and then it can be useful to query data in the validator.

I have not found a way to obtain the originating adapter object (to participate in that transaction), so I create a new one as well. If it would be possible to wire a new DataAdapter to an existing transaction/connection, that could be useful as well.

Queries performed during validation can be blocked by prior insert/update operations performed in the same transaction where the entity being validated belongs to. Because when using a new DataAdapter in the validator it gets a new db connection as well.

In this case you may need to perform the validation query with an isolation level that does not honor any blocked rows:

adapter.StartTransaction(System.Data.IsolationLevel.ReadUncommitted, "Validate");

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 19-Mar-2018 17:12:17   

Pilo wrote:

I have not found a way to obtain the originating adapter object (to participate in that transaction), so I create a new one as well. If it would be possible to wire a new DataAdapter to an existing transaction/connection, that could be useful as well.

You can, but it requires a subclass of DataAccessAdapter. Override the CreateNewPhysicalTransaction/Connection methods and instead of calling the base method (which creates new ones) you simply return an existing one, which you store in the instance through e.g. a property.

alternatively, you could use a TransactionScope, and simply create new adapters and transactions on the fly: the commit of the transactionscope will then commit all transactions.

Frans Bouma | Lead developer LLBLGen Pro