Exception when using one-to-one properties in a criteria projections
Description
I get the following exception when using a one-to-one property in a criteria projection:
NHibernate.Exceptions.GenericADOException: could not execute query [ SELECT this_.USERID as y0_ FROM USER this_ ] [SQL: SELECT this_.USERID as y0_ FROM USER this_] ---> System.IndexOutOfRangeException: Index was outside the bounds of the array. at NHibernate.Loader.Criteria.CriteriaLoader.GetResultColumnOrRow(Object[] row, IResultTransformer customResultTransformer, IDataReader rs, ISessionImplementor session) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Criteria\CriteriaLoader.cs:line 101 at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 360 at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 468 at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 246 at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1590 — End of inner exception stack trace — at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1599
Using many-to-one projections on the other hand does work. The difference seems to be the AbstractType.GetColumnSpan method which returns a hard coded zero in the OneToManyType override and a non-zero value in the ManyToOneType override.
My thoughts exactly Oskar, and if it can't be supported for technical reasons then a more meaningful error would be nice.
Oskar Berggren
June 8, 2012 at 6:55 AM
https://nhibernate.jira.com/browse/NH-3176#icft=NH-3176 was about collections. one-to-one sounds more natural to support, technically there shouldn't be much difference from many-to-one. It might be a feature request rather then a bug though.
The NH unit test project is a little overwhelming but I'm able to reproduce the issue by adding the following test to the MergeFixture class. I doubt this is an appropriate place for such a test to live permanently, I just needed a convenient place to use the one-to-one Person.Detail property.
[Test] public void OneToOneProjection() { using (var s = OpenSession()) { var p = new Person {Name = "steve"}; new PersonalDetails {SomePersonalDetail = "I have big feet", Person = p}; s.Save(p); s.Flush(); s.CreateCriteria<Person>().SetProjection(Projections.Property("Details")).List(); } }
I get the following exception when using a one-to-one property in a criteria projection:
NHibernate.Exceptions.GenericADOException: could not execute query
[ SELECT this_.USERID as y0_ FROM USER this_ ]
[SQL: SELECT this_.USERID as y0_ FROM USER this_] ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
at NHibernate.Loader.Criteria.CriteriaLoader.GetResultColumnOrRow(Object[] row, IResultTransformer customResultTransformer, IDataReader rs, ISessionImplementor session) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Criteria\CriteriaLoader.cs:line 101
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 360
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 468
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 246
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1590
— End of inner exception stack trace —
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\GitHub\nhibernate\nhibernate-core\src\NHibernate\Loader\Loader.cs:line 1599
Using many-to-one projections on the other hand does work. The difference seems to be the AbstractType.GetColumnSpan method which returns a hard coded zero in the OneToManyType override and a non-zero value in the ManyToOneType override.