为什么我的NHibernate查询失败并带有IndexOutOfRangeException?

时间:2009-11-02 18:58:22

标签: fluent-nhibernate nhibernate-mapping

我正在使用Fluent NHibernate,在某些情况下我的查询失败了System.IndexOutOfRangeException

该问题似乎与映射中使用转义列名称并调用 CreateSQLQuery().AddEntity() 的组合有关。如果没有列需要转义,或者我改为使用CreateCriteria<Employee>(),那么它可以正常工作。

public class Employee {
    public virtual string EmployeeNumber { get; set; }
    public virtual string Username { get; set; }
}

public class EmployeeMapping : ClassMap<Employee> {
    public EmployeeMapping() {
        Table("Employees");
        Id(e => e.EmployeeNumber)
            .Column("No_");
        Map(e => e.Username)
            .Column("`E-mail Login`"); // Note the escaped column name
    }
}

public class SqlRepository {
    ...
    public IList<Employee> ListEmployees() {
        using (ISession session = _sessionBuilder.GetSession()) {
            return session
                .CreateSQLQuery("SELECT No_, [E-mail Login] FROM Employees")
                .AddEntity(typeof(Employee))
                .List<Employee>();
        }
    }
}

致电ListEmployees()会产生System.IndexOutOfRangeException

但是,如果我将CreateSQLQuery().AddEntity()调用更改为CreateCriteria<Employee>(),则可以正常使用。但我的实际SQL更复杂,所以我认为这对我不起作用。

或者,如果我将用户名映射更改为Map(e => e.Username).Column("Username");并将SQL查询更改为SELECT No_, [E-mail Login] AS Username FROM Employees,则可以正常工作。但这会破坏我的代码中使用CreateCriteria<Employee>()的其他地方的映射。我目前无法更改表格架构。

为什么会失败?除了我提到的,你还有其他建议吗?感谢。

我正在使用Fluent NHibernate 1.0,NHibernate 2.1.0.4000和SQL Server 2005。

这是堆栈跟踪:

 NHibernate.ADOException was unhandled
   Message="could not execute query\r\n[ SELECT No_, [E-mail Login] FROM Employees ]\r\n[SQL: SELECT No_, [E-mail Login] FROM Employees]"
   Source="NHibernate"
   SqlString="SELECT No_, [E-mail Login] FROM Employees"
   StackTrace:
     at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
     at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
     at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
     at NHibernate.Loader.Custom.CustomLoader.List(ISessionImplementor session, QueryParameters queryParameters)
     at NHibernate.Impl.SessionImpl.ListCustomQuery(ICustomQuery customQuery, QueryParameters queryParameters, IList results)
     at NHibernate.Impl.SessionImpl.List(NativeSQLQuerySpecification spec, QueryParameters queryParameters, IList results)
     at NHibernate.Impl.SessionImpl.List[T](NativeSQLQuerySpecification spec, QueryParameters queryParameters)
     at NHibernate.Impl.SqlQueryImpl.List[T]()
     at NHibernateTest.Core.SqlRepository.ListEmployees() in C:\dev\NHibernateTest\NHibernateTest\SqlRepository.cs:line 14
     at NHibernateTest.Console.Program.Main(String[] args) in C:\dev\NHibernateTest\NHibernateTest.Console\Program.cs:line 8
     at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
     at System.Threading.ThreadHelper.ThreadStart()
   InnerException: System.IndexOutOfRangeException
     Message="[E-mail Login]"
     Source="System.Data"
     StackTrace:
    at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName)
    at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name)
    at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name)
    at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name)
    at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
    at NHibernate.Type.AbstractType.Hydrate(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
    at NHibernate.Persister.Entity.AbstractEntityPersister.Hydrate(IDataReader rs, Object id, Object obj, ILoadable rootLoadable, String[][] suffixedPropertyColumns, Boolean allProperties, ISessionImplementor session)
    at NHibernate.Loader.Loader.LoadFromResultSet(IDataReader rs, Int32 i, Object obj, String instanceClass, EntityKey key, String rowIdAlias, LockMode lockMode, ILoadable rootPersister, ISessionImplementor session)
    at NHibernate.Loader.Loader.InstanceNotYetLoaded(IDataReader dr, Int32 i, ILoadable persister, EntityKey key, LockMode lockMode, String rowIdAlias, EntityKey optionalObjectKey, Object optionalObject, IList hydratedObjects, ISessionImplementor session)
    at NHibernate.Loader.Loader.GetRow(IDataReader rs, ILoadable[] persisters, EntityKey[] keys, Object optionalObject, EntityKey optionalObjectKey, LockMode[] lockModes, IList hydratedObjects, ISessionImplementor session)
    at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies)
    at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
    at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
    at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
     InnerException: 

1 个答案:

答案 0 :(得分:3)

我通过使用别名作为列名并使用结果转换器来实现它。它不理想,因为它忽略了我的映射并需要为每列设置别名。但它现在有效。

public class SqlRepository {
    ...
    public IList<Employee> ListEmployees() {
        using (ISession session = _sessionBuilder.GetSession()) {
            return session
                .CreateSQLQuery(@"
                    SELECT No_ AS EmployeeNumber, [E-mail Login] AS Username 
                    FROM Employees")
                .AddScalar("EmployeeNumber", NHibernateUtil.String)
                .AddScalar("Username", NHibernateUtil.String)
                .SetResultTransformer(Transformers.AliasToBean<Employee>())
                .List<Employee>();
        }
    }
}

有更好的解决方案吗? (流利的)NHibernate中是否存在导致原始问题的错误?