2009-11-02 89 views
4

我使用流利的NHibernate,在某些情況下,我的查詢失敗,System.IndexOutOfRangeException爲什麼我的NHibernate查詢因IndexOutOfRangeException失敗?

看來這個問題已使用逃脫列名(S)的映射,並呼籲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>()的其他地方的映射。我目前無法更改表格模式。

這是爲什麼會失敗?除了我提到的之外,你還有其他建議嗎?謝謝。

我使用功能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: 

回答

2

我把它通過使用別名爲列名的工作和使用結果變換器。這並不理想,因爲它忽略了我的映射並需要爲每列設置一個別名。但它現在起作用。

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中可能存在導致原始問題的錯誤?