Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Query cache + entity with Enum id + child collection => NullReferenceException when loading from second level cache #3643

Open
cwatzl opened this issue Jan 22, 2025 · 0 comments

Comments

@cwatzl
Copy link

cwatzl commented Jan 22, 2025

After upgrading an old legacy project from NH 5.2.7 to 5.5.2 I encountered a peculiar regression bug:

  • Root Entity has an Id property having an enum type, and a one-to-many relationship with another entity
  • Second level cache and query cache is used for querying the Entity; child collection is fetched eagerly in the query in question
  • First execution of the query (with unpopulated cache) works; subsequent executions fail with NullReferenceException thrown in TypeHelper.

Example model:

	class Entity
	{
		private readonly ICollection<ChildEntity> _children = new List<ChildEntity>();
		public virtual EntityId Id { get; protected set; }
		public virtual IEnumerable<ChildEntity> Children => _children.AsEnumerable();
	}

	class ChildEntity
	{
		public virtual int Id { get; protected set; }
	}

	enum EntityId
	{
		Id1,
		Id2
	}

Mapping:

mapper.Class<Entity>(
	rc =>
	{
		rc.Id(x => x.Id);
		rc.Bag(
			x => x.Children,
			m =>
			{
				m.Access(Accessor.Field);
				m.Key(k => k.Column("EntityId"));
			},
			r => r.OneToMany());
		rc.Cache(
			cm =>
			{
				cm.Include(CacheInclude.All);
				cm.Usage(CacheUsage.ReadWrite);
			});
	});

mapper.Class<ChildEntity>(
	rc =>
	{
		rc.Id(x => x.Id);
		rc.Cache(
			cm =>
			{
				cm.Include(CacheInclude.All);
				cm.Usage(CacheUsage.ReadWrite);
			});
	});

Query:

session
    .Query<Entity>()
    .FetchMany(x => x.Children)
    .WithOptions(opt => opt.SetCacheable(true))
    .ToList();

Exception thrown on second and all subsequent query executions:

NHibernate.Exceptions.GenericADOException : Could not execute query[SQL: SQL not available]
  ----> System.NullReferenceException : Object reference not set to an instance of an object.
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results, Object filterConnection) in C:\dev\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 563
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) in C:\dev\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 523
   at NHibernate.Impl.AbstractSessionImpl.List[T](IQueryExpression query, QueryParameters parameters) in C:\dev\nhibernate-core\src\NHibernate\Impl\AbstractSessionImpl.cs:line 182
   at NHibernate.Impl.AbstractQueryImpl2.List[T]() in C:\dev\nhibernate-core\src\NHibernate\Impl\AbstractQueryImpl2.cs:line 111
   at NHibernate.Linq.DefaultQueryProvider.ExecuteList[TResult](Expression expression) in C:\dev\nhibernate-core\src\NHibernate\Linq\DefaultQueryProvider.cs:line 111
   at NHibernate.Linq.NhQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in C:\dev\nhibernate-core\src\NHibernate\Linq\NhQueryable.cs:line 65
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NHibernate.Test.NHSpecificTest.GHXXXX.FixtureByCode.LoadEntityByNameWithQueryCache() in C:\dev\nhibernate-core\src\NHibernate.Test\NHSpecificTest\GHXXXX\FixtureByCode.cs:line 108
   at NHibernate.Test.NHSpecificTest.GHXXXX.FixtureByCode.LoadsEntityWithEnumIdAndChildrenUsingQueryCache() in C:\dev\nhibernate-core\src\NHibernate.Test\NHSpecificTest\GHXXXX\FixtureByCode.cs:line 95
--NullReferenceException
   at NHibernate.Type.TypeHelper.InitializeCollections(Object[] cacheRow, Object[] assembleRow, IDictionary`2 collectionIndexes, ISessionImplementor session) in C:\dev\nhibernate-core\src\NHibernate\Type\TypeHelper.cs:line 137
   at NHibernate.Cache.StandardQueryCache.InitializeCollections(ICacheAssembler[] returnTypes, ISessionImplementor session, IList assembleResult, IList cacheResult) in C:\dev\nhibernate-core\src\NHibernate\Cache\StandardQueryCache.cs:line 554
   at NHibernate.Cache.StandardQueryCache.GetResultFromCacheable(QueryKey key, ICacheAssembler[] returnTypes, Boolean isNaturalKeyLookup, ISessionImplementor session, IList cacheable) in C:\dev\nhibernate-core\src\NHibernate\Cache\StandardQueryCache.cs:line 582
   at NHibernate.Cache.StandardQueryCache.Get(QueryKey key, QueryParameters queryParameters, ICacheAssembler[] returnTypes, ISet`1 spaces, ISessionImplementor session) in C:\dev\nhibernate-core\src\NHibernate\Cache\StandardQueryCache.cs:line 147
   at NHibernate.Cache.QueryCacheExtensions.Get(IQueryCache queryCache, QueryKey key, QueryParameters queryParameters, ICacheAssembler[] returnTypes, ISet`1 spaces, ISessionImplementor session) in C:\dev\nhibernate-core\src\NHibernate\Cache\IQueryCache.cs:line 147
   at NHibernate.Loader.Loader.GetResultFromQueryCache(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IQueryCache queryCache, QueryKey key) in C:\dev\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1943
   at NHibernate.Loader.Loader.ListUsingQueryCache(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces) in C:\dev\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1887
   at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces) in C:\dev\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1842
   at NHibernate.Loader.Hql.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) in C:\dev\nhibernate-core\src\NHibernate\Loader\Hql\QueryLoader.cs:line 302
   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) in C:\dev\nhibernate-core\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs:line 156
   at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) in C:\dev\nhibernate-core\src\NHibernate\Engine\Query\HQLQueryPlan.cs:line 115
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results, Object filterConnection) in C:\dev\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 553
[...]
cwatzl added a commit to cwatzl/nhibernate-core that referenced this issue Jan 22, 2025
cwatzl added a commit to cwatzl/nhibernate-core that referenced this issue Jan 22, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant