Skip to content

ConditionalProjection containing the correlation to outer query fails to determine projection type #2454

Closed
@delta-emil

Description

@delta-emil

Here is the code that causes the exception:

Entity classes:

	public class Project
	{
		public virtual Guid Id { get; set; }
		public virtual string Name { get; set; }
	}

	public class Component
	{
		public virtual Guid Id { get; set; }
		public virtual string Name { get; set; }
		public virtual Project Project { get; set; }
	}

	public class Tag
	{
		public virtual Guid Id { get; set; }
		public virtual string Name { get; set; }
		public virtual Component Component1 { get; set; }
		public virtual Component Component2 { get; set; }
	}

Mapping:

	mapper.Class<Project>(rc =>
	{
		rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
		rc.Property(x => x.Name);
	});

	mapper.Class<Component>(rc =>
	{
		rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
		rc.Property(x => x.Name);
		rc.ManyToOne(x => x.Project, m => { m.Column("ProjectId"); m.NotNullable(true); });
	});

	mapper.Class<Tag>(rc =>
	{
		rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
		rc.Property(x => x.Name);
		rc.ManyToOne(x => x.Component1, m => { m.Column("Component1Id"); m.NotNullable(true); });
		rc.ManyToOne(x => x.Component2, m => { m.Column("Component2Id"); m.NotNullable(false); });
	});

Attempted query:

	ICriteria tagCriteria = session.CreateCriteria(typeof(Tag), "t");
	tagCriteria.CreateCriteria("Component1", "c1");
	tagCriteria.CreateCriteria("Component2", "c2", JoinType.LeftOuterJoin);

	IProjection projectNameProjection;
	{
		// create correlated subquery
		var projectCriteria = DetachedCriteria.For(typeof(Project), "p");

		// the problem appears when the outer query references are in a Conditional:
		var conditionalCorrelationProjection = Projections.Conditional(
			Restrictions.IsNotNull(Projections.Property("t.Component2")),
			Projections.Property("c2.Project"),
			Projections.Property("c1.Project"));
		projectCriteria.Add(Restrictions.EqProperty("p.Id", conditionalCorrelationProjection));

		projectCriteria.SetProjection(Projections.Property("p.Name"));

		projectNameProjection = Projections.SubQuery(projectCriteria);
	}

	tagCriteria.Add(Restrictions.Eq(projectNameProjection, "Beta"));

	// throws exception
	tagCriteria.List();

Exception data:

 SubqueryCorrelatedThroughConditional
   Source: FixtureByCode.cs line 41
   Duration: 458 ms

  Message: 
    NHibernate.QueryException : could not resolve property: c2.Project of: NHibernate.Test.NHSpecificTest.GH9999.Project
  Stack Trace: 
    AbstractPropertyMapping.ToType(String propertyName) line 37
    AbstractEntityPersister.ToType(String propertyName) line 2065
    CriteriaQueryTranslator.GetType(ICriteria subcriteria, String propertyName) line 810
    PropertyProjection.GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery) line 50
    ConditionalProjection.GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery) line 56
    SimpleProjection.GetColumnCount(ICriteria criteria, ICriteriaQuery criteriaQuery) line 79
    SimpleProjection.GetColumnAliases(Int32 position, ICriteria criteria, ICriteriaQuery criteriaQuery) line 41
    ConditionalProjection.ToSqlString(ICriteria criteria, Int32 position, ICriteriaQuery criteriaQuery) line 50
    CriterionUtil.GetProjectionColumns(IProjection projection, ICriteriaQuery criteriaQuery, ICriteria criteria) line 98
    CriterionUtil.GetColumnNamesAsSqlStringParts(IProjection projection, ICriteriaQuery criteriaQuery, ICriteria criteria) line 71
    CriterionUtil.GetColumnNamesAsSqlStringParts(String propertyName, IProjection projection, ICriteriaQuery criteriaQuery, ICriteria criteria) line 61
    PropertyExpression.ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery) line 75
    CriteriaQueryTranslator.GetWhereCondition() line 281
    CriteriaJoinWalker.ctor(IOuterJoinLoadable persister, CriteriaQueryTranslator translator, ISessionFactoryImplementor factory, ICriteria criteria, String rootEntityName, IDictionary`2 enabledFilters) line 48
    SubqueryExpression.ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery) line 65
    SubqueryProjection.ToSqlString(ICriteria criteria, Int32 loc, ICriteriaQuery criteriaQuery) line 44
    CriterionUtil.GetProjectionColumns(IProjection projection, ICriteriaQuery criteriaQuery, ICriteria criteria) line 98
    CriterionUtil.GetColumnNamesUsingProjection(IProjection projection, ICriteriaQuery criteriaQuery, ICriteria criteria) line 53
    CriterionUtil.GetColumnNamesForSimpleExpression(String propertyName, IProjection projection, ICriteriaQuery criteriaQuery, ICriteria criteria, ICriterion criterion, Object value) line 42
    SimpleExpression.ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery) line 81
    CriteriaQueryTranslator.GetWhereCondition() line 281
    CriteriaJoinWalker.ctor(IOuterJoinLoadable persister, CriteriaQueryTranslator translator, ISessionFactoryImplementor factory, ICriteria criteria, String rootEntityName, IDictionary`2 enabledFilters) line 48
    CriteriaLoader.ctor(IOuterJoinLoadable persister, ISessionFactoryImplementor factory, CriteriaImpl rootCriteria, String rootEntityName, IDictionary`2 enabledFilters) line 69
    SessionImpl.List[T](CriteriaImpl criteria) line 1711
    CriteriaImpl.List[T]() line 296
    CriteriaImpl.List() line 283
    ByCodeFixture.SubqueryCorrelatedThroughConditional() line 100

I will post a pull request with a potential fix later.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions