Migrate LLBLGen PRO Runtime version to 5.10

Posts   
 
    
guyronen
User
Posts: 26
Joined: 02-Mar-2021
# Posted on: 26-Dec-2023 18:32:08   

hello I was migrate the Runtime version from 5.7.2 to the New version 5.10 also generated DLLs by 5.10 designer .Net Framework version 4.8 (Target version was a fix on one of the releases)

I Followed migrate instructions for 5.8 https://www.llblgen.com/Documentation/5.10/LLBLGen%20Pro%20RTF/migratingcode.htm#breaking-changes-v5.8

Now I am getting Exception : NullReferenceException Message: "Object reference not set to an instance of an object." Source: "SD.LLBLGen.Pro.ORMSupportClasses" StackTrace : " at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.Dispose(Boolean isDisposing)\r\n at ....

did i missed any thing ? what can Couse this Exception or how can I fix it ? thank you

My Implementation Code :

the Inherited DataAccessAdapter class:

public class NessDataAccessAdapter : DataAccessAdapter

protected override QueryCreationManager CreateQueryCreationManager(IPersistenceInfoProvider persistenceInfoProvider)
        {
            return new NessQueryCreationManager(this,persistenceInfoProvider);
  }

the Inherited QueryCreationManager class

public class NessQueryCreationManager : QueryCreationManager 

protected override IRetrievalQuery CreateSelectDQ(QueryParameters parameters)
        {
            long maxNumberOfItemsToReturn = (long)parameters.RowsToTake;
            if (parameters.RowsToTake == 0)
            {
                parameters.RowsToTake = (int)this.GetMaxNumberOfItemsToReturn(maxNumberOfItemsToReturn);
            }
            IRetrievalQuery updatedQuery = base.CreateSelectDQ(parameters);

            updatedQuery.Command.CommandText = updatedQuery.Command.CommandText.ToUpper();

            this._traceHelper.TraceQuery(updatedQuery, "CreateSelectDQ-after using entity relations.", _traceLLBLGENQueryesTitle);

            return updatedQuery;
        }
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39617
Joined: 17-Aug-2003
# Posted on: 27-Dec-2023 09:25:34   

The dispose method is pretty small:

protected virtual void Dispose(bool isDisposing)
{
    // Check to see if Dispose has already been called.
    if(!_isDisposed)
    {
        if(isDisposing)
        {
            _containedTransaction.Dispose();
            DisposePostponedDisposeCandidates();
            _isDisposed = true;
        }
    }
}

_containedTransaction is the TransactionAdapter object which basically creates connections and transactions and makes sure they're wired up correctly

So without the full code you added to NessDataAccessAdapter we can't see what it might be.

We have a query creation manager for tracking which queries are created in the unittests, which looks like this:

public class CommandTrackingQueryCreationManager : QueryCreationManager
{
    public CommandTrackingQueryCreationManager(DataAccessAdapterCore containingAdapter, IPersistenceInfoProvider persistenceInfoProvider) 
        : base(containingAdapter, persistenceInfoProvider)
    {}
    
    
    protected override IRetrievalQuery CreateSelectDQ(QueryParameters parameters)
    {
        if(this.GeneratedCommands == null)
        {
            this.GeneratedCommands = new List<DbCommand>();
        }
        var toReturn = base.CreateSelectDQ(parameters);
        this.GeneratedCommands.Add(toReturn.Command);
        return toReturn;
    }
    

    public List<DbCommand> GeneratedCommands { get; private set; }
}

And all we do is indeed override CreateQueryCreationManager:

protected override QueryCreationManager CreateQueryCreationManager(IPersistenceInfoProvider persistenceInfoProvider)
{
    _queryCreationManager = new CommandTrackingQueryCreationManager(this, persistenceInfoProvider);
    return _queryCreationManager;
}

We keep it around as it contains the test data we need but it's not necessary to do so if it doesn't contain data, as it's already kept around in the DataAccessAdapterCore class, so that's not it (as you new up a new one when the method is called, which is ok, it's called once)

Could you give more info so we can try to reproduce it? With the info you gave it's not possible to build a repro case. Additionally, the runtime sourcecode is available on the website (My account -> downloads -> version -> extras section), you could build the runtime from source and see what it is exactly that is null.

Frans Bouma | Lead developer LLBLGen Pro
guyronen
User
Posts: 26
Joined: 02-Mar-2021
# Posted on: 27-Dec-2023 15:06:47   

Hi , thank you for your reply it seems that I implemented it correct as your description. i'v checkd again and that code wich is on the server side is working ok also the disposal. But, The exception occurs on another implementation for the DataAccessAdapter on the client side. on this ClientDataAccessAdapter there is no usage of CreateSelectDQ an there for no needed to override for QueryCreationManager. so, I guess the problem is not related to that issue . all is fetching good and using all methods are working fine . it happen just when unloading a form which resolved that classes and try to dispose all object related when close. I have added an override for Dispose just for debugging this issue and its not there on the original code. the exception accurse same as I mentioned before at on this line - base.Dispose(isDisposi Remarking this line all works but I don't want to give away Dispose.. and trying to figure what is the problem. same code worked without any problem on the previous version(5.7.2). here is my code :

 public class ClientDataAccessAdapter : DataAccessAdapterBase

    {

        public ClientDataAccessAdapter()

            : base(null)       

        {

 

        }
 

        [NessDependency]

        public IDataQueriesContract Proxy { get; set; }

        public override void FetchEntityCollection(QueryParameters parameters)

        {           

           int pageNumber = parameters.RowsToTake==0 ?  0: parameters.RowsToSkip / parameters.RowsToTake;

           pageNumber += 1;

            try

            {

                TypeInfo entityTypeInfo = this.GetEntityTypeInfo((IEntityCollection2)parameters.CollectionToFetch); 

                IEntityCollection2 serverResult = this.Proxy.Get(entityTypeInfo, parameters.FilterRelationsAsBucket, parameters.RowsToTake, parameters.SorterToUse, (IPrefetchPath2)parameters.PrefetchPathToUse,

            parameters.ExcludedIncludedFields,pageNumber, parameters.RowsToTake); 

                this.MergeResult((IEntityCollection2)parameters.CollectionToFetch, serverResult);

            }

            catch (Exception ex)

            {

                throw new InfrastructureDataQueriesGetOperationException(ex);

            } 

            //this.Proxy.Get(parameters);

            //base.FetchEntityCollection(parameters);

        } 

        /// <summary>

        /// Adds all entities in <paramref name="serverResult"/> to <paramref name="clientResult"/>.

        /// </summary>

        /// <param name="clientResult">The result to be returned to the caller.</param>

        /// <param name="serverResult">The result returned from the server.</param>

        private void MergeResult(IEntityCollection2 clientResult, IEntityCollection2 serverResult)

        {

            foreach (IEntity2 entity in serverResult)

            {

                clientResult.Add(entity);

            }

        } 

        /// <summary>

        /// Extracts the type of entity in the result root collection and translates it to <see cref="TypeInfo"/> to be possible to

        /// serialize it when passing the request to the server.

        /// </summary>

        /// <param name="collection">The collection containing the target entity type.</param>

        /// <returns><see cref="TypeInfo"/></returns>

        private TypeInfo GetEntityTypeInfo(IEntityCollection2 collection)

        {

            Type entityType = collection.GetType().GetGenericArguments()[0];

            return TypeInfo.Create(entityType);

        }

        private TypeInfo GetEntityTypeInfo(QueryParameters parameters)

        {

            Type entityType = parameters.CollectionToFetch.GetType().GetGenericArguments()[0];

            return TypeInfo.Create(entityType);

        } 

        #region DataAccessAdapterBase members     

        protected override DynamicQueryEngineBase CreateDynamicQueryEngine()

       {

            return new DynamicQueryEngine();

            //return this.PostProcessNewDynamicQueryEngine(new DynamicQueryEngine());

        } 

        bool _isDisposing = false;

        protected override void Dispose(bool isDisposing)

        {

            if (!_isDisposing)

            {

                if (isDisposing)

                {

                    base.Dispose(isDisposing);

                    _isDisposing = true;

                }

            } 

        }

        #endregion

    }

I didn't find were to download this: "the runtime sourcecode is available on the website (My account -> downloads -> version -> extras section), you could build the runtime from source and see what it is exactly that is null" to try debugging the inner code and see were there's an exception inside.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39617
Joined: 17-Aug-2003
# Posted on: 28-Dec-2023 09:38:08   

Ah you're not using the generated class there, so you skip the call to InitClassPhase2() which creates the TransactionAdapter which is assumed to be there at the Dispose() method in the DataAccessAdapterCore class.

I think it's sufficient enough not to call the base class' Dispose() method in your overriden Dispose() method. The base Dispose method disposes any entities still caught in a transaction but as you don't use that logic on the client, it's not necessary to call Dispose there.

To get access to the sourcecode, log in with your customerid + password, then you'll see My Account in the menu. Click on that and on the right you see the versions, click on 5.10 and then scroll down to the 'Extras' section. You'll then see the LLBLGen Pro Source code download archive.

Frans Bouma | Lead developer LLBLGen Pro
guyronen
User
Posts: 26
Joined: 02-Mar-2021
# Posted on: 01-Jan-2024 12:37:23   

ok thank you Otis i'm overriding the Dispose to ignore the inner dispose. I had another problem with resolving the DataAccessAdapterCore while using the new implementations of QueryCreationManager. we use unity IOC to resolve classes. for now iv managed to fix it . problem resolved for now and will open new thread if needed. thank you very much

guyronen
User
Posts: 26
Joined: 02-Mar-2021
# Posted on: 04-Jan-2024 17:17:45   

Hello After Migrating our LLBLGen Pro Runtime from 5.7 to 5.10 I have problem receiving connection string

ErrorMessage : No connection string specified. Please specify a connection string in the app/web.config file or through the RuntimeConfiguration system.
StackTrace:

   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.CreateNewPhysicalConnection(String connectionString)

   at SD.LLBLGen.Pro.ORMSupportClasses.AdapterSpecific.TransactionAdapter.CreateConnection(String connectionString)

   at SD.LLBLGen.Pro.ORMSupportClasses.TransactionBase.AssureConnectionIsPresent()

   at SD.LLBLGen.Pro.ORMSupportClasses.Adapter.QueryCreationManager.CreateSelectDQ(QueryParameters parameters)

   at Ness.ProvidentFunds.Common.DataAccess.Extensions.Services.NessQueryCreationManager.CreateSelectDQ(QueryParameters parameters) in c:\Builds\6\Gaya\GAYA_BUILD.4.8_AUTO\Sources\DataAccess\All\Ness.ProvidentFunds.Common.DataAccess.Extensions\NessDataAccessAdapter\Services\NessQueryCreationManager.cs:line 125

   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchEntityCollectionInternal(QueryParameters parameters)

   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchEntityCollection(QueryParameters parameters)

   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.<>c__DisplayClass10_0.<FetchEntityCollection>b__0()

   at Ness.ProvidentFunds.Common.DataAccess.Extensions.NessDataAccessAdapter.FetchEntityCollection(QueryParameters parameters) in c:\Builds\6\Gaya\GAYA_BUILD.4.8_AUTO\Sources\DataAccess\All\Ness.ProvidentFunds.Common.DataAccess.Extensions\NessDataAccessAdapter\NessDataAccessAdapter.cs:line 153

   at Ness.ProvidentFunds.Common.DataAccess.Extensions.DataAccessAdapterExceptionsDecorator.FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList excludedIncludedFields, Int32 pageNumber, Int32 pageSize) in c:\Builds\6\Gaya\GAYA_BUILD.4.8_AUTO\Sources\DataAccess\All\Ness.ProvidentFunds.Common.DataAccess.Extensions\NessDataAccessAdapter\DataAccessAdapterExceptionsDecorator.cs:line 531

we use a custom configuration for connection string from web.config and not the default key from appSettings (<add key="Main.ConnectionString.Oracle (ODP.NET)…")

therefor on our DataAccessAdapter I have override the ConnectionString Property

public override string ConnectionString

        {

            get

            {

              

                return m_connectionString;

            }

            set

            {

                if (m_connectionString == null)

                {

                    IConnectionStringProvider provider = new ConfigurationDalAppConfigConnStringProvider();

                    m_connectionString = provider.GetConnectionString();                

                }

                base.ConnectionString = m_connectionString;

            }

        }

On previews version all CreateSelectDQ functions been at the DataAccessAdapter and received the connection string

In new version since 5.8 refactoring the CreateSelectDQ moved to the new class QueryCreationManager which not contains the property ConnectionString

I can't override it at that deriving class and there for its probably go to default config value Main.ConnectionString.Oracle (ODP.NET).

How can I set or override to the custom connection string config value for that new class as well as done for the DataAccessAdapter?

Thank you

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 05-Jan-2024 09:59:50   

Please create a new thread for the last issue (connection string).