我正在使用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:
答案 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中是否存在导致原始问题的错误?