Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
310 views
in Technique[技术] by (71.8m points)

ado.net - Nhibernate FieldNameLookup throws IndexOutOfRangeException

Every now and then we get this very weird error

NHibernate.ADOException: could not execute query
[ SELECT this_.Id as Id37_0_, this_.AREA_ID as AREA2_37_0_, this_.BAT_CHK as BAT3_37_0_, this_.BAT_COD as BAT4_37_0_, this_.BBEACT as BBEACT37_0_, this_.CREDATE as CREDATE37_0_, this_.DEST_LOC as DEST7_37_0_, this_.DOCNR as DOCNR37_0_, this_.DOCTYPE as DOCTYPE37_0_, this_.DUTY_STATUS as DUTY10_37_0_, this_.EAN as EAN37_0_, this_.EXCEPTION_REASON as EXCEPTION12_37_0_, this_.ERROR_TEXT as ERROR13_37_0_, this_.FLOWTYPE as FLOWTYPE37_0_, this_.GOODS_STATUS as GOODS15_37_0_, this_.INSERT_DATETIME as INSERT16_37_0_, this_.MATNR as MATNR37_0_, this_.MVTTYPE as MVTTYPE37_0_, this_.ORDNR as ORDNR37_0_, this_.PACK_ID as PACK20_37_0_, this_.PALNR as PALNR37_0_, this_.PRDACT as PRDACT37_0_, this_.QTYLOAD as QTYLOAD37_0_, this_.SCANNR as SCANNR37_0_, this_.SEQ as SEQ37_0_, this_.SOURCE_LOC as SOURCE26_37_0_, this_.STATUS as STATUS37_0_, this_.TEXT as TEXT37_0_, this_.USER_ID as USER29_37_0_, this_.WH_ID as WH30_37_0_ FROM ZZHTR_RCV this_ WHERE this_.DOCNR = ? and this_.ORDNR = ? and this_.MVTTYPE = ? and this_.WH_ID = ? ]
Positional parameters:  #0>10972365/O #0>1300196311 #0>O #0>NL02
[SQL: <same as above>]
---> System.IndexOutOfRangeException: Id37_0_
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.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, 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)
--- End of inner exception stack trace ---
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, ISet1 querySpaces, IType[] resultTypes)
at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session)
at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)
at NHibernate.Impl.CriteriaImpl.List(IList results)
at NHibernate.Impl.CriteriaImpl.List[T]()
at Rhino.Commons.RepositoryImplBase1.FindAll(DetachedCriteria criteria, Order[] orders)
at Rhino.Commons.Repository1.FindAll(DetachedCriteria criteria, Order[] orders)

The problem is that this error is not showing up every time. I see it's the Id column, but don't understand why it is having issues there. I'm pretty sure the mapping is OK

Mapping:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="XX.Business"
                   namespace="XX.Business"
                   default-lazy="true">
  <class name="XX.Business.Receive, XX.Business" table="ZZHTR_RCV" lazy="true">
    <id name="Id" type="int">
      <generator class="identity" />
    </id>
    <property name="AreaCode" column="AREA_ID"/>
    <property name="BatchCheck" column="BAT_CHK"/>
    <property name="BatchCode" column="BAT_COD"/>
    <property name="BbeAct" column="BBEACT"/>
    <property name="CreationDate" column="CREDATE" not-null="true"/>
    <property name="DestinationLocation" column="DEST_LOC"/>
    <property name="DocNr" column="DOCNR"/>
    <property name="DocType" column="DOCTYPE"/>
    <property name="DutyStatus" column="DUTY_STATUS"/>
    <property name="Ean" column="EAN"/>
    <property name="ExceptionReason" column="EXCEPTION_REASON"/>
    <property name="ErrorText" column="ERROR_TEXT"/>
    <property name="FlowType" column="FLOWTYPE"/>
    <property name="GoodsStatus" column="GOODS_STATUS"/>
    <property name="InsertDateTime" column="INSERT_DATETIME" not-null="true"/>
    <property name="MaterialNr" column="MATNR"/>
    <property name="MovementType" column="MVTTYPE"/>
    <property name="OrderNr" column="ORDNR"/>
    <property name="ManufacturingBatch" column="PACK_ID"/>
    <property name="PalletNr" column="PALNR"/>
    <property name="ProdAct" column="PRDACT"/>
    <property name="QuantityLoad" column="QTYLOAD"/>
    <property name="ScanNr" column="SCANNR"/>
    <property name="Sequence" column="SEQ"/>
    <property name="SourceLocation" column="SOURCE_LOC"/>
    <property name="Status" column="STATUS"/>
    <property name="Text" column="TEXT"/>
    <property name="UserId" column="USER_ID"/>
    <property name="WarehouseCode" column="WH_ID"/>


  </class>
</hibernate-mapping>

Class:

[XmlRoot("ZZHTR_RCV")]
    public class Receive : DomainObject
    {
        [XmlElement("AREA_ID")]
        public virtual string AreaCode { get; set; }
        [XmlElement("BAT_CHK")]
        public virtual string BatchCheck { get; set; }
        [XmlElement("BAT_COD")]
        public virtual string BatchCode { get; set; }
        [XmlElement("BBEACT")]
        public virtual DateTime? BbeAct { get; set; }
        [XmlElement("CREDATE")]
        public virtual DateTime CreationDate { get; set; }
        [XmlElement("DEST_LOC")]
        public virtual string DestinationLocation { get; set; }
        [XmlElement("DOCNR")]
        public virtual string DocNr { get; set; }
        [XmlElement("DOCTYPE")]
        public virtual string DocType { get; set; }
        [XmlElement("DUTY_STATUS")]
        public virtual DutyStatus DutyStatus { get; set; }
        [XmlElement("EAN")]
        public virtual string Ean { get; set; }
        [XmlElement("ERROR_TEXT")]
        public virtual string ErrorText { get; set; }
        [XmlElement("FLOWTYPE")]
        public virtual string FlowType { get; set; }
        [XmlElement("GOODS_STATUS")]
        public virtual GoodsStatus GoodsStatus { get; set; }
        [XmlElement("INSERT_DATETIME")]
        public virtual DateTime InsertDateTime { get; set; }
        [XmlElement("MATNR")]
        public virtual string MaterialNr { get; set; }
        [XmlElement("MVTTYPE")]
        public virtual string MovementType { get; set; }
        [XmlElement("ORDNR")]
        public virtual string OrderNr { get; set; }
        [XmlElement("PACK_ID")]
        public virtual string ManufacturingBatch { get; set; }
        [XmlElement("PALNR")]
        public virtual string PalletNr { get; set; }
        [XmlElement("PRDACT")]
        public virtual DateTime? ProdAct { get; set; }
        [XmlElement("QTYLOAD")]
        public virtual int QuantityLoad { get; set; }
        [XmlElement("SCANNR")]
        public virtual string ScanNr { get; set; }
        [XmlElement("SEQ")]
        public virtual int Sequence { get; set; }
        [XmlElement("SOURCE_LOC")]
        public virtual string SourceLocation { get; set; }
        [XmlElement("STATUS")]
        public virtual MobileProcessingStatus Status { get; set; }
        [XmlElement("TEXT")]
        public virtual string Text { get; set; }
        [XmlElement("USER_ID")]
        public virtual string UserId { get; set; }
        [XmlElement("WH_ID")]
        public virtual string WarehouseCode { get; set; }
        [XmlElement("EXCEPTION_REASON")]
        public virtual ExceptionReason ExceptionReason { get; set; }
        public virtual string Prodline
        {
            get
            {
                if(string.IsNullOrEmpty(this.PalletNr) || !this.PalletNr.Length.Equals(18))
                {
                    return "000";
                }
                else
                {
                    return this.PalletNr.Substring(8, 3);
                }
            }
        }
        public virtual string EERPProcessOrder { get; set; }

    }

Id is inherited from DomainObject:

public abstract class DomainObject:IDomainObject
    {
        [DataMember]
        public virtual int Id { get; set; }

Table:

[Id] [int] IDENTITY(1,1) NOT NULL,
    [AREA_ID] [nvarchar](255) NOT NULL,
    [BAT_CHK] [nvarchar](255) NULL,
    [BAT_COD] [nvarchar](255) NULL,
    [BBEACT] [datetime] NULL,
    [CREDATE] [datetime] NOT NULL,
    [DEST_LOC] [nvarchar](255) NULL,
    [DOCNR] [nvarchar](255) NOT NULL,
    [DOCTYPE] [nchar](2) NOT NULL,
    [DUTY_STATUS] [int] NOT NULL,
    [EAN] [nvarchar](255) NOT NULL,
    [ERROR_TEXT] [nvarchar](255) NULL,
    [EXCEPTION_REASON] [int] NULL,
    [FLOWTYPE] [nvarchar](255) NULL,
    [GOODS_STATUS] [int] NOT NULL,
    [INSERT_DATETIME] [datetime] NOT NULL,
    [MATNR] [nvarchar](255) NOT NULL,
    [MVTTYPE] [nchar](1) NOT NULL,
    [ORDNR] [nvarchar](255) NOT NULL,
    [PACK_ID] [nvarchar](255) NULL,
    [PALNR] [nvarchar](255) NOT NULL,
    [PRDACT] [datetime] NULL,
    [QTYLOAD] [int] NOT NULL,
    [SCANNR] [nvarchar](255) NOT NULL,
    [SEQ] [int] NOT NULL,
    [SOURCE_LOC] [nvarchar](255) NULL,
    [STATUS] [int] NOT NULL,
    [TEXT] [nvarchar](255) NULL,
    [USER_ID] [nvarchar](255) NOT NULL,
    [WH_ID] [nvarchar](255) NOT NULL,

Can anyone help please?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

We - and others - have also encountered this problem. It seems to be related to multi-threaded access to the not-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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...