NHibernate System.IndexOutOfRangeException

时间:2009-11-03 13:44:10

标签: nhibernate

我有一个非常简单的类,它给出了一个奇怪的错误。该类只有1个属性,查询非常简单。最棘手的部分是,这似乎是随机发生的。在收到此错误后,通常刷新页面会使其成为一种方式,并且应用程序不会再次出现错误。

这可能是数据库连接的问题吗?

我得到了:

[IndexOutOfRangeException: Department5_]
   System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName) +4839010
   System.Data.SqlClient.SqlDataReader.GetOrdinal(String name) +67
   NHibernate.Driver.NHybridDataReader.GetOrdinal(String name) +46
   NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name) +87
   NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) +62
   NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session) +213
   NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) +301
   NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +1422
   NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +114
   NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) +205

[ADOException: could not execute query
[ select department0_.Department as Department5_ from tblDepartments department0_ where department0_.Department like 'CBS - %' ]
[SQL: select department0_.Department as Department5_ from tblDepartments department0_ where department0_.Department like 'CBS - %']]
   NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) +383
   NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) +52
   NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) +183
   NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) +102
   NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) +684
   NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) +816
   NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) +277
   NHibernate.Impl.SessionImpl.List(String query, QueryParameters parameters) +235
   NHibernate.Impl.QueryImpl.List() +224
   DispatchBoard.Models.Repository.Find(String hql) +76
   DispatchBoard.Controllers.HomeController.Filter() +48
   lambda_method(ExecutionScope , ControllerBase , Object[] ) +39
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +178
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +24
   System.Web.Mvc.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7() +52
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +254
   System.Web.Mvc.<>c__DisplayClassc.<InvokeActionMethodWithFilters>b__9() +19
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +192
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +399
   System.Web.Mvc.Controller.ExecuteCore() +126
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +27
   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
   System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +151
   System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +57
   System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +7
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

这是我的班级

public class Department : IObject {
    public virtual string Name { get; set; }
}

hbm文件

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="DispatchBoard.Models.Department, DispatchBoard" table="tblDepartments">
        <id name="Name" column="Department" type="String" length="50">
            <generator class="assigned" />
        </id>

    </class>
</hibernate-mapping>

这是HQL查询

var hql = "from Department d where d.Name like 'CBS - %'";
_session.CreateQuery(hql).List<T>();

7 个答案:

答案 0 :(得分:11)

通常,当您在NHibernate中获得IndexOutOfRangeException时,这是因为您将属性映射了两次,或者将两个属性映射到同一列。检查列名称。

它可能是随机发生的,因为冲突只出现在某个数据星座中。

答案 1 :(得分:7)

我们 - 和其他人 - 最近和过去也遇到过这个问题。它似乎与对非线程安全的SqlConnection的多线程访问有关。以下非常长(!)帖子包含更多示例以及有关该问题的更多详细信息:SQLDataReader.GetOrdinal() fails rarely with IndexOutOfRange。 bbzippo说:

  

“很明显,SqlDataReader读取   从结果中遗留下来的结果集   以前的查询执行相同   连接几秒钟。“

不幸的是,我没有找到任何真正的解释,为什么在一段时间没有问题的代码中突然发生这种异常。

在给定帖子中提出的一些建议是:

  1. 关闭连接池,因此您的连接字符串将如下所示: "Data Source=Sql2005;Initial Catalog=MyDbName;User Id=MyLogin;Password=MyPass;Pooling=false"(这很可能意味着您的应用会受到性能影响,但肯定会有效)
  2. 将引用static个实例的所有SqlConnection代码重构为non-static
  3. 修复对SqlConnection的可能的多线程访问(这可能不那么容易......)
  4. 我仍在尝试在我们的应用程序中找到错误的来源,但这并不容易,因为我无法在我们的实时环境之外重现它。在上面提到的帖子中Matt Neerincx [MSFT] suggests in one of his answers使用不同的连接字符串,从而为应用程序的不同部分使用不同的连接池,以帮助缩小问题的根源。

    我发现有关此问题的另一个读法是在hibernate论坛上:https://forum.hibernate.org/viewtopic.php?p=2386963,其中一张海报在多线程场景中也存在延迟加载问题。

    希望这会引导任何人朝着正确的方向寻找解决方案。

    奥利弗

    P.S。这是我对Nhibernate FieldNameLookup throws IndexOutOfRangeException

    的回答的副本

答案 2 :(得分:4)

当我尝试将空值映射到不可为空的属性(即整数)时,我遇到了这个错误。确保你确保sql值不可为空,或者只是让c#属性为nullable(public virtual int? NumberOfPoints { get; set; }

答案 3 :(得分:2)

我试了将近3年来追踪我们系统中的GetOrdinal错误的原因(它不使用nHibernate)。对我们来说,在我们的连接字符串中添加“Enlist = False”会使问题完全消失。我们昨天从大约160个错误(大多数是GetOrdinal错误)变成了昨天的26个错误,而不是一个GetOrdinal。

显然,Enlist参数(默认情况下为True)告诉ADO将连接分组并以原子方式处理它们作为单个事务,但它似乎不起作用。我们的代码中绝对没有事务处理指令,但ADO正在对连接进行分组并在数据中导致意外结果。

如果您没有在代码中处理SQL事务,请尝试此设置,您可能会像我们一样获得积极的结果。

麦克

答案 4 :(得分:0)

你在映射文件中放了一个长度= 50,你确定数据库列是varchar(50),如果NHibernate获取一个更长的字符串,它可能会导致你的错误。我通常会留下长度属性。

答案 5 :(得分:0)

如果列名称和Mapping属性名称未正确匹配,系统通常会抛出IndexOutOfRangeException异常。

答案 6 :(得分:0)

我在一段时间内遇到了类似的错误。我从一个原生SQL&#34;中得到了错误。查询,使用Session.CreateSQLQuery(字符串)创建。我之前使用过类似的查询并取得了很好的成功,但这次问题是我查询的是一个具有子类的实体类型,并且它们被映射为数据库中的每个类的表。

我注意到,如果我执行普通查询,让NHibernate生成SQL,它将包含一个格式为&#34的列;当subclass_table.Parent_class_id不为null时为1,当parent_class.Id不为null时为1 0结束为clazz _&#34;。

所以,在修复之前我的查询是这样的:

SELECT TOP 1 *
FROM Table WITH (TABLOCKX) 
WHERE Column = 'Value'

(强制独占表锁定是我用&#34;原生SQL&#34;首先进行查询的原因......)

我所做的只是添加一个名为&#34; clazz _&#34;的列,它开始起作用。在这种情况下,我知道结果将不包括子类的实例,所以我只是将值硬编码为零:

SELECT TOP 1 *, 0 as clazz_ 
FROM Table WITH (TABLOCKX) 
WHERE Column = 'Value'

如果结果可能包含子类的实例,那么这将更复杂。那么我可能真的必须包含子类表的左外连接,以及NHibernate使用它的方式的CASE子句。