NHibernate System.IndexOutOfRangeException
Asked Answered
B

7

14

I've got a really simple class that is giving a strange error. The class only has 1 property and the query is really simple. The stranglest part is that this seems to happen randomly. After getting this error usually refreshing the page makes it go a way and the application doesn't get the errror again.

Could this be a problem with the database connection?

I'm getting:

[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

Here is my class

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

The hbm file

<?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>

and here is the HQL query

var hql = "from Department d where d.Name like 'CBS - %'";
_session.CreateQuery(hql).List<T>();
Boice answered 3/11, 2009 at 13:44 Comment(3)
So you say this class / mapping / query are complete, there is nothing missing here?Filthy
There are a few queries that happen before this one, using different classes, but this is the complete query and mapping. It doesn't make sense to me.Boice
Before a query, NHibernate flushes the session to make sure to query to updated data. So this could occur because of in-memory changes you do before this query. Although the stack trace doesn't look like this, still try by calling session.Flush() before the query to see if it happens during flush or during the query. Check the mappings of this other classes anyway.Filthy
F
13

usually, when you get an IndexOutOfRangeException in NHibernate it is because you mapped a property twice, or mapped two properties to the same column. Check the column names.

It's possible that it occurs randomly because the conflict only shows up in a certain data constellation.

Filthy answered 3/11, 2009 at 13:50 Comment(3)
Thanks for the suggestion. The query is to a class that only has 1 property (Name) and no relationships. And if the refresh the page (run the query again) it will work fine. It gets the same data everytime. There are no variations to this query. In the hbm file above I have only defined the id mapping. It isn't mapped twice.Boice
I had messed up my mapping properties in a different way. Your comment pointed me in the right direction. Thanks!Mick
In my case, I was idParent property and many-to-one Parents with this same column. Thanks! Works fine.Conlon
S
8

We - and others - have also had this problem recently and in the past. It seems to be related to multi-threaded access to the non-thread-safe SqlConnection. The following really long (!) post contains more examples and some more detail on the issue: SQLDataReader.GetOrdinal() fails rarely with IndexOutOfRange. There bbzippo states:

"It's evident that SqlDataReader reads a result set left over from the previous query executed on the same connection a couple of seconds ago."

Unfortunately, I haven't found any real explanation of why this exception occurs suddenly in code that has been working without a problem for some time.

Some of the suggestions made in the given thread are:

  1. Turn connection pooling off, so your connection string would look like e.g. "Data Source=Sql2005;Initial Catalog=MyDbName;User Id=MyLogin;Password=MyPass;Pooling=false" (this most likely will mean a performance hit for your application but is sure to work)
  2. Refactor all static code referencing your SqlConnection instance(s) to non-static
  3. Fix possible multi-threaded access to your SqlConnections (this might not be that easy...)

I'm still trying to find the source of the error in our application but it's not that easy because I haven't been able to reproduce it outside our live environment. Matt Neerincx [MSFT] suggests in one of his answers in the above mentioned post to use different connection strings and thus different connection pools for different parts of your application to help narrow down the source of the problem.

Another read I found regarding this problem was on the hibernate forums: https://forum.hibernate.org/viewtopic.php?p=2386963, where one poster also had problems with lazy-loading in a multi-threaded scenario.

Hope this will guide anyone in the right direction for a fix.

Oliver

P.S. This is a copy of my answer to Nhibernate FieldNameLookup throws IndexOutOfRangeException

Sacrament answered 3/7, 2010 at 22:36 Comment(2)
I think your solution works with more than NHibernate. Specifically if you are having trouble with AspDotNetStorefront.Bethune
We use UCommerce and Umbraco. UCommerce uses NHibernate. We got thousand of this IndexOutOfRangeException errors. With putting pooling on false it seems to be solved now...Electroanalysis
C
4

I've gotten this error when I tried to map a null value to a non-nullable property (i.e. an integer). make sure that either you make sure that the sql value is non-nullable, or just make the c# property nullable (public virtual int? NumberOfPoints { get; set; })

Chiles answered 28/2, 2013 at 22:32 Comment(0)
T
2

I tried for nearly 3 years to track down the cause of GetOrdinal errors in our system (which does not use nHibernate). For us, adding "Enlist=False" to our connection strings made the problem go away completely. We've gone from about 160 errors per day (mostly GetOrdinal errors) to 26 errors yesterday, and not a single GetOrdinal.

Apparently the Enlist argument (which is True by default) tells ADO to group connections and handle them atomically as a single transaction, but it doesn't seem to work. We have absolutely no transaction-handling directives in our code, yet ADO was grouping connections and causing unexpected results in our data.

If you're not handling SQL transactions in your code, try this setting and you may get positive results just like we did.

Mike

Terrorstricken answered 24/1, 2012 at 16:8 Comment(0)
U
0

You've put a length=50 in the mapping file, are you sure the database column is varchar(50), if NHibernate fetches a longer string it could be causing your error. I would usually leave the length attribute out.

Uncommonly answered 4/11, 2009 at 21:38 Comment(0)
G
0

Usually system throws IndexOutOfRangeException exception if the columns names and Mapping property names are not matched properly.

Glogau answered 18/4, 2013 at 10:25 Comment(0)
V
0

I struggled with a very similar error for some time. I was getting the error from a "native SQL" query, created with the Session.CreateSQLQuery(string). I had used similar queries with good success before, but this time the problem was that I was querying for an entity type that does have a subclass, and they were mapped as table-per-class in the database.

I noticed that if I do a normal query, letting NHibernate generate the SQL, it will include a column in the format like "case when subclass_table.Parent_class_id is not null then 1 when parent_class.Id is not null then 0 end as clazz_".

So, before the fix my query was something like this:

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

(Forcing the exclusive table lock is the reason I'm doing the query with the "native SQL" in the first place...)

What I did was just add a column called "clazz_", and it started to work. In this case I KNOW for sure that the results will not include instances of the subclass, so I'm just hard-coding the value as zero:

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

If it would be possible for the result to include instances of the subclass, this would be more complicated. Then I would probably really have to include the left outer join for the subclass's table, and the CASE clause in the way NHibernate uses it.

Voyeur answered 25/11, 2016 at 13:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.