2009-11-02 6 views
4

Fluent NHibernate를 사용하고 있는데 어떤 경우에는 내 쿼리가 System.IndexOutOfRangeException으로 실패합니다.내 NHibernate 쿼리가 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>(); 
     } 
    } 
} 

System.IndexOutOfRangeException으로 전화를 걸면 결과가 ListEmployees()이됩니다.

그러나 CreateSQLQuery().AddEntity() 전화를 CreateCriteria<Employee>()으로 변경하면 정상적으로 작동합니다. 하지만 내 실제 SQL은 더 복잡해서 나를 위해 잘 작동하지 않을 것이라고 생각합니다.

또는 사용자 이름 매핑을 Map(e => e.Username).Column("Username");으로 변경하고 SQL 쿼리를 SELECT No_, [E-mail Login] AS Username FROM Employees으로 변경하면 올바르게 작동합니다. 그러나 이것은 내 코드에서 CreateCriteria<Employee>()을 사용하는 다른 장소에 대한 매핑을 깨뜨릴 것입니다. 그리고 지금은 테이블 스키마를 변경할 수 없습니다.

왜 이것이 실패할까요? 제가 언급 한 것 외에 다른 제안이 있습니까? 감사.

것은 내가 NHibernate에 2.1.0.4000 및 SQL Server 여기에 2005

유창함 NHibernate에 1.0를 사용하고하는 스택 추적입니다 :

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>(); 
     } 
    } 
} 

더 좋은 해결책이 있습니까? 원래의 문제를 일으키는 (Fluent) NHibernate에 버그가있을 수 있습니까?

관련 문제