Description
Alan Carroll created an issue — 18th February 2016, 15:50:29:
The code below generates the exception shown. Client, company, and vendor name are all AnsiString type, with a length of 200. The problem stems from the type equality comparison, which uses the string length.
NHibernateUtil.AnsiString
does not have a length defined. Perhaps exact type equality is not what we want here.var associate = Projections.Conditional( Restrictions.IsNotNull(Projections.Property(() => this.root.Client)), Projections.Property(() => this.client.Name), Projections.Conditional( Restrictions.IsNotNull(Projections.Property(() => this.root.Company)), Projections.Property(() => this.company.Name), Projections.Conditional( Restrictions.IsNotNull(Projections.Property(() => this.root.Vendor)), Projections.Property(() => this.vendor.Name), Projections.Constant(null, NHibernateUtil.AnsiString))));
{noformat:title=Exception}
Both true and false projections must return the same types.
But True projection returns: <NHibernate.Type.AnsiStringType>
And False projection returns: [NHibernate.Type.AnsiStringType]{noformat:title=Stack Trace} [HibernateException: Both true and false projections must return the same types. But True projection returns: [NHibernate.Type.AnsiStringType] And False projection returns: [NHibernate.Type.AnsiStringType]] NHibernate.Criterion.ConditionalProjection.GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery) NHibernate.Criterion.SimpleProjection.GetColumnCount(ICriteria criteria, ICriteriaQuery criteriaQuery) NHibernate.Criterion.SimpleProjection.GetColumnAliases(Int32 position, ICriteria criteria, ICriteriaQuery criteriaQuery) NHibernate.Criterion.ConditionalProjection.ToSqlString(ICriteria criteria, Int32 position, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters) NHibernate.Criterion.ConditionalProjection.ToSqlString(ICriteria criteria, Int32 position, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters) NHibernate.Criterion.ConditionalProjection.ToSqlString(ICriteria criteria, Int32 position, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters) NHibernate.Criterion.AliasedProjection.ToSqlString(ICriteria criteria, Int32 position, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters) NHibernate.Criterion.ProjectionList.ToSqlString(ICriteria criteria, Int32 loc, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters) NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetSelect(IDictionary`2 enabledFilters) NHibernate.Loader.Criteria.CriteriaJoinWalker..ctor(IOuterJoinLoadable persister, CriteriaQueryTranslator translator, ISessionFactoryImplementor factory, ICriteria criteria, String rootEntityName, IDictionary`2 enabledFilters) NHibernate.Loader.Criteria.CriteriaLoader..ctor(IOuterJoinLoadable persister, ISessionFactoryImplementor factory, CriteriaImpl rootCriteria, String rootEntityName, IDictionary`2 enabledFilters) NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) NHibernate.Impl.CriteriaImpl.List(IList results) NHibernate.Impl.CriteriaImpl.List<T>() NHibernate.Criterion.QueryOver`1.List<U>() NHibernate.Criterion.QueryOver`1.NHibernate.IQueryOver<TRoot>.List<U>()
Since AnsiStringType does not have a public constructor, we cannot create our own with a matching length. My temporary workaround is to create my own class that inherits from AbstractStringType, and specify the length.
private class MyAnsiStringType : NHibernate.Type.AbstractStringType { public MyAnsiStringType() : base (new NHibernate.SqlTypes.AnsiStringSqlType(200)) { } public override string Name { get { return "AnsiString"; } } }
This works, since the lengths are all the same, but I should be able to do a conditional that returns strings of varying lengths. Furthermore, I should be able to return any string type, because this is valid SQL (SQL Server at least).
select case when 1 = 1 then '1' when 1 = 2 then N'2' end
Alan Carroll added a comment — 14th June 2017, 16:54:36:
I've found a simpler way to work around this issue using the built-in
NHibernate.Type.TypeFactory
.TypeFactory.GetAnsiStringType(200)