Skip to content

JoinAlias not working as expected after NHibernate update #2185

Open
@cjay99

Description

@cjay99

Hello,

we have encountered a problem with NHIbernate after updating form 5.1.1 to 5.2.5.
We are using JoinAlias and projection to gain extra performance at some points in the program.

I've created a test solution which is encapsulated from our program to show you the different behaviour between the two version (Attachment NHibernate_Test.zip, containing a VS Solution):
NHibernate_test.zip

Here's the Query which is causing the issue (Also in the test solution):

public static IList<WorkstepFeatureLiteRequestBean> PerformSelect(long? featureSetTemplateId, long? featureSetId)
{
	using (var session = _sessionFactory.OpenSession())
	{
		using (var transaction = session.BeginTransaction(IsolationLevel.ReadCommitted))
		{
			Workstep workstepAlias = null;
			Feature featureAlias = null;
			FeatureSet featureSetAlias = null;
			FeatureSetTemplate featureSetTemplateAlias = null;
			FeatureTemplate featureTemplateAlias = null;
			FeatureType featureTypeAlias = null;

			var selectedTypes = BaseData.FeatureTypes.Take(2).ToList();
			var query = session.QueryOver(() => workstepAlias);

			if (featureSetTemplateId.HasValue)
			{
				query = query
					.JoinAlias(x => x.FeatureSetTemplate, () => featureSetTemplateAlias)
					.And(() => featureSetTemplateAlias.Id == featureSetTemplateId.Value);
			}

			if (featureSetId.HasValue)
			{
				query = query
					.JoinAlias(x => x.FeatureSet, () => featureSetAlias)
					.And(() => featureSetAlias.Id == featureSetId);
			}
			
			if (!featureSetId.HasValue)
			{
				query = query.JoinAlias(x => x.FeatureSet, () => featureSetAlias);
			}
			
			if (!featureSetTemplateId.HasValue)
			{
				query = query.JoinAlias(x => x.FeatureSetTemplate, () => featureSetTemplateAlias);
			}
			
			WorkstepFeatureLiteRequestBean bean = null;
			var fullQuery = query
				.JoinQueryOver(x => x.FeatureSet.Features, () => featureAlias)
				.JoinQueryOver(x => x.FeatureTemplate, () => featureTemplateAlias)
				.JoinQueryOver(x => x.FeatureType, () => featureTypeAlias)
				.And(x => x.FeatureKey.IsIn(selectedTypes))
				.SelectList(x => x
					.Select(() => workstepAlias.Id).WithAlias(() => bean.WorkstepId)
					.Select(() => workstepAlias.Uuid).WithAlias(() => bean.WorkstepUuid)
					.Select(() => workstepAlias.Name).WithAlias(() => bean.WorkstepName)
					.Select(() => workstepAlias.JointIndex).WithAlias(() => bean.WorkstepJointIndex)
					.Select(() => featureSetTemplateAlias.Name).WithAlias(() => bean.FeatureSetTemplateName)
					.Select(() => featureSetAlias.Name).WithAlias(() => bean.FeatureSetName)
					.Select(() => featureAlias.Id).WithAlias(() => bean.FeatureId)
					.Select(() => featureAlias.Uuid).WithAlias(() => bean.FeatureUuid)
					.Select(() => featureTemplateAlias.Name).WithAlias(() => bean.FeatureName)
					.Select(() => featureTypeAlias.FeatureKey).WithAlias(() => bean.FeatureType)
				)
				.TransformUsing(Transformers.AliasToBean<WorkstepFeatureLiteRequestBean>());

			var filteredWorksteps = fullQuery.List<WorkstepFeatureLiteRequestBean>();
			transaction.Commit();
			return filteredWorksteps;
		}
	}
}

The SQL NHibernate generates looks like this in version 5.1.1 (which is fine and working):

SELECT this_.id                AS y0_,
       this_.uuid              AS y1_,
       this_.NAME              AS y2_,
       this_.jointindex        AS y3_,
       featureset2_.NAME       AS y4_,
       featureset1_.NAME       AS y5_,
       featureali3_.id         AS y6_,
       featureali3_.uuid       AS y7_,
       featuretem4_.NAME       AS y8_,
       featuretyp5_.featurekey AS y9_
FROM   nh_ja_workstep this_
       INNER JOIN nh_ja_featuresettemplate featureset2_
               ON this_.featuresettemplate_id = featureset2_.id
       INNER JOIN nh_ja_featureset featureset1_
               ON this_.featureset_id = featureset1_.id
       INNER JOIN nh_ja_feature featureali3_
               ON featureset1_.id = featureali3_.featureset_id
       INNER JOIN nh_ja_featuretemplate featuretem4_
               ON featureali3_.featuretemplate_id = featuretem4_.id
       INNER JOIN nh_ja_featuretype featuretyp5_
               ON featuretem4_.featuretype_id = featuretyp5_.id
WHERE  featuretyp5_.featurekey IN ( @p0, @p1 )  

But in version 5.2.5 the produced statement looks like this (which is not working):

SELECT this_.id                AS y0_,
       this_.uuid              AS y1_,
       this_.NAME              AS y2_,
       this_.jointindex        AS y3_,
       featureset2_.NAME       AS y4_,
       featureset1_.NAME       AS y5_,
       featureali3_.id         AS y6_,
       featureali3_.uuid       AS y7_,
       featuretem4_.NAME       AS y8_,
       featuretyp5_.featurekey AS y9_
FROM   nh_ja_workstep this_
       INNER JOIN nh_ja_featuresettemplate featureset2_
               ON this_.featuresettemplate_id = featureset2_.id
       INNER JOIN nh_ja_featureset featureset1_
               ON this_.featureset_id = featureset1_.id
WHERE  featuretyp5_.featurekey IN ( @p0, @p1 ) 

Serveral joins are missing in the produced statement and cannot be executed by the database (Tested on MSSQL 14 & Oracle 12c).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions