2009-11-03 14 views
13

Tengo una clase muy simple que está dando un error extraño. La clase solo tiene 1 propiedad y la consulta es realmente simple. La parte más estrangulada es que esto parece suceder al azar. Después de obtener este error, por lo general, la actualización de la página lo hace funcionar y la aplicación no vuelve a obtener el error.NHibernate System.IndexOutOfRangeException

¿Podría ser un problema con la conexión de la base de datos?

que estoy recibiendo:

[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 

Aquí está mi clase

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

El archivo 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> 

y aquí está la consulta HQL

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

¿Así que usted dice que esta clase/mapeo/consulta están completos, no hay nada que falta aquí? –

+0

Hay algunas consultas que suceden antes de esta, utilizando diferentes clases, pero esta es la consulta completa y el mapeo. No tiene sentido para mí. – modernzombie

+0

Antes de realizar una consulta, NHibernate vacía la sesión para asegurarse de consultar datos actualizados. Esto podría ocurrir debido a los cambios en la memoria que usted hace antes de esta consulta. Aunque el seguimiento de la pila no se ve así, intente llamar a session.Flush() antes de la consulta para ver si ocurre durante la descarga o durante la consulta. Verifique las asignaciones de estas otras clases de todos modos. –

Respuesta

11

generalmente, cuando obtiene IndexOutOfRangeException en NHibernate, se debe a que asignó una propiedad dos veces o asignó dos propiedades a la misma columna. Verifique los nombres de las columnas.

Es posible que ocurra al azar porque el conflicto solo aparece en una determinada constelación de datos.

+0

Gracias por la sugerencia. La consulta es para una clase que solo tiene 1 propiedad (Nombre) y ninguna relación. Y si actualiza la página (ejecuta la consulta nuevamente) funcionará bien. Obtiene la misma información cada vez. No hay variaciones en esta consulta. En el archivo hbm anterior, solo he definido la asignación de identificación. No está mapeado dos veces. – modernzombie

+0

Había estropeado mis propiedades de mapeo de una manera diferente. Tu comentario me indicó la dirección correcta. ¡Gracias! – thebiggestlebowski

+0

En mi caso, yo era propiedad de IdParent y padres varios a uno con esta misma columna. ¡Gracias! Funciona bien. –

0

Has puesto una longitud = 50 en el archivo de mapeo, estás seguro de que la columna de la base de datos es varchar (50), si NHibernate busca una cadena más larga podría estar causando tu error. Normalmente dejaba el atributo de longitud fuera.

7

Nosotros, y otros, también hemos tenido este problema recientemente y en el pasado. Parece estar relacionado con el acceso de subprocesos múltiples al SqlConnection no seguro para subprocesos. La siguiente publicación realmente larga (!) contiene más ejemplos y algunos detalles adicionales sobre el problema: SQLDataReader.GetOrdinal() fails rarely with IndexOutOfRange. Hay bbzippo estados:

"Es evidente que SqlDataReader lee un conjunto de resultados sobrante de la consulta anterior ejecutados en la misma conexión hace un par de segundos."

Lamentablemente, no he encontrado ninguna explicación real de por qué esta excepción se produce de repente en el código que ha estado funcionando sin problemas durante un tiempo.

Algunas de las sugerencias formuladas en el subproceso dado son:

  1. conexión Encienda la puesta en común fuera, por lo que la cadena de conexión se vería como por ejemplo, "Data Source=Sql2005;Initial Catalog=MyDbName;User Id=MyLogin;Password=MyPass;Pooling=false" (esto muy probablemente significará un impacto en el rendimiento para su aplicación, pero es seguro que funcione)
  2. Refactor todo static código de incluir su SqlConnection instancia (s) de non-static
  3. Fijar el posible acceso de múltiples subprocesos a sus SqlConnection s (esto podría no ser tan fácil ...)

Todavía estoy tratando de encontrar el origen del error en nuestra aplicación, pero no es tan fácil porque no he podido reproducirlo fuera de nuestro entorno en vivo.Matt Neerincx [MSFT] suggests in one of his answers en la publicación mencionada anteriormente para utilizar diferentes cadenas de conexión y, por lo tanto, diferentes grupos de conexiones para diferentes partes de su aplicación para ayudar a reducir el origen del problema.

Otra lectura que encontré con respecto a este problema fue en los foros de hibernación: https://forum.hibernate.org/viewtopic.php?p=2386963, donde un póster también tuvo problemas con la carga lenta en un escenario de subprocesos múltiples.

Espero que esto guíe a cualquier persona en la dirección correcta para una solución.

Oliver

P.S. Esta es una copia de mi respuesta a Nhibernate FieldNameLookup throws IndexOutOfRangeException

+0

Creo que su solución funciona con más de NHibernate. Específicamente si tiene problemas con AspDotNetStorefront. – CaptainBli

+0

Utilizamos UCommerce y Umbraco. UCommerce usa NHibernate. Tenemos miles de estos errores de IndexOutOfRangeException. Con poner pooling en falso, parece estar resuelto ahora ... – Hans

2

Intenté durante casi 3 años rastrear la causa de los errores de GetOrdinal en nuestro sistema (que no utiliza nHibernate). Para nosotros, agregar "Enlist = False" a nuestras cadenas de conexión hizo que el problema desapareciera por completo. Hemos pasado de aproximadamente 160 errores por día (la mayoría de los errores GetOrdinal) a 26 errores ayer, y ni un solo GetOrdinal.

Aparentemente, el argumento Enlist (que es True por defecto) le dice a ADO que debe agrupar conexiones y manejarlas atómicamente como una transacción única, pero parece que no funciona. No tenemos absolutamente ninguna directiva de manejo de transacciones en nuestro código, pero ADO estaba agrupando conexiones y causando resultados inesperados en nuestros datos.

Si no está manejando transacciones de SQL en su código, pruebe esta configuración y puede obtener resultados positivos al igual que nosotros.

Mike

4

que he recibido este error cuando trataba de asignar un valor nulo a una propiedad no anulable (es decir, un entero). asegurarse de que, o bien se asegura de que el valor de SQL no es anulable, o simplemente tomar la propiedad C# anulable (public virtual int? NumberOfPoints { get; set; })

0

Por lo general, el sistema tiros IndexOutOfRangeException excepción si los nombres de las columnas y los nombres de propiedad de asignación no se corresponden correctamente.

0

Luché con un error muy similar durante algún tiempo. Recibí el error de una consulta de "SQL nativo", creada con la Session.CreateSQLQuery (cadena). Antes había utilizado consultas similares con buen éxito, pero esta vez el problema era que estaba consultando un tipo de entidad que tiene una subclase, y se mapearon como tabla por clase en la base de datos.

Me di cuenta de que si hago una consulta normal, dejar que NHibernate genere el SQL, incluirá una columna en el formato como "case when subclass_table.Parent_class_id no es nulo, entonces 1 cuando parent_class.Id no es null, entonces 0 end como clazz_ ".

Por lo tanto, antes de la corrección de mi consulta era algo como esto:

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

(Forzar el bloqueo de tabla exclusivo es la razón por la que estoy haciendo la consulta con el "SQL nativo" en el primer lugar .. .)

Lo que hice fue simplemente agregar una columna llamada "clazz_", y comenzó a funcionar. En este caso, estoy segura de que los resultados no incluirán las instancias de la subclase, así que estoy difíciles de codificar el valor de cero:

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

Si sería posible para el resultado de incluir los casos de la subclase, esto sería más complicado.Entonces, probablemente tendría que incluir realmente la combinación externa izquierda para la tabla de la subclase, y la cláusula CASE en la forma en que NHibernate lo usa.