问题
I'm hoping that someone can help me with this issue. I've been racking my brain and my project is due very soon. Thank You in advance.
I'm receiving an index out of range exception when inserting a new record. After searching endlessly for information, it was suggested that the number of column values in my mapping do not match that in my persistent class. However, I counted and re-counted, and they seem to match. As you can see by my code below, I'm using NHibernate.Mapping.Attributes to do my mapping. Maybe I'm doing something wrong there.
I finally downloaded the NHibernate source and debugged through my problem. Below is the insert statement that NHibernate is attempting to build:
{INSERT INTO WTSLIB33T.PRODDATA (PSTAT, PCONO, PDVNO, PWKTY, PCRTY, PTSID, PCNNO, PDTTK, PJBNO, PSJNO, PTKNO, PCWNO, PWKAR, PWKDC, PWKCD, PCNWO, PWDNO, PDESC, PDCCD, PHRS, PUNIT, PSEQ, PCUST) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}
As you can see, the number of parameters matches the number of fields in the list. I've also matched up this generated insert with my class and what I found is that the PSEQ and PCUST columns are out of order with my persistent class. Then, while debugging through the Dehydrate function I found two possible issues. The first is that I noticed that the call to the NullSafeSet function sets parameter 0 to what my PSEQ field should be set to but parameter 0 in the insert statement is PSTAT.
The second issue I noticed is that the very last call "index += ArrayHelper.CountTrue(includeColumns[i]);" in the Dehydrate function leaves the index variable at 23 which is correct; however, the next call "IdentifierType.NullSafeSet(statement, id, index, session);" ,where it checks for a row id, passes in index 23 which would be out of range. This value should be 22 for the zero based array.
protected int Dehydrate(object id, object[] fields, object rowId, bool[] includeProperty, bool[][] includeColumns, int table, IDbCommand statement, ISessionImplementor session, int index)
{
if (log.IsDebugEnabled)
{
log.Debug("Dehydrating entity: " + MessageHelper.InfoString(this, id, Factory));
}
// there's a pretty strong coupling between the order of the SQL parameter
// construction and the actual order of the parameter collection.
for (int i = 0; i < entityMetamodel.PropertySpan; i++)
{
if (includeProperty[i] && IsPropertyOfTable(i, table))
{
PropertyTypes[i].NullSafeSet(statement, fields[i], index, includeColumns[i], session);
index += ArrayHelper.CountTrue(includeColumns[i]);
}
if (rowId != null)
{
// TODO H3.2 : support to set the rowId
// TransactionManager.manager.SetObject(ps, index, rowId);
// index += 1;
throw new NotImplementedException("support to set the rowId");
}
else if (id != null)
{
IdentifierType.NullSafeSet(statement, id, index, session);
index += IdentifierColumnSpan;
}
return index;
}
MY PERSISTENT CLASS:
[NHibernate.Mapping.Attributes.Class(0, Schema = WTSLIB33T, Table = "PRODDATA", NameType = typeof(ProddataDAO), Lazy = true)] public class ProddataDAO : Object // : INotifyPropertyChanged { public ProddataDAO() { }
public ProddataDAO(string PSTAT, decimal PCONO, decimal PDVNO, decimal PSEQ, string PWKTY, string PCRTY,
decimal PTSID, decimal PCUST, decimal PCNNO, decimal PDTTK, string PJBNO, string PSJNO, decimal PTKNO,
string PCWNO, string PWKAR, string PWKDC, string PWKCD, string PCNWO, decimal PWDNO, string PDESC,
decimal PDCCD, decimal PHRS, decimal PUNIT)
{
_PSTAT = PSTAT;
_PCONO = PCONO;
_PDVNO = PDVNO;
_PSEQ = PSEQ;
_PWKTY = PWKTY;
_PCRTY = PCRTY;
_PTSID = PTSID;
_PCUST = PCUST;
_PCNNO = PCNNO;
_PDTTK = PDTTK;
_PJBNO = PJBNO;
_PSJNO = PSJNO;
_PTKNO = PTKNO;
_PCWNO = PCWNO;
_PWKAR = PWKAR;
_PWKDC = PWKDC;
_PWKCD = PWKCD;
_PCNWO = PCNWO;
_PWDNO = PWDNO;
_PDESC = PDESC;
_PDCCD = PDCCD;
_PHRS = PHRS;
_PUNIT = PUNIT;
}
//public event PropertyChangedEventHandler PropertyChanged;
private decimal _PSEQ;
//[NHibernate.Mapping.Attributes.Id(0, Name="PSEQ", Column="PSEQ", Type="Decimal")]
[NHibernate.Mapping.Attributes.CompositeId(1, UnsavedValue=NHibernate.Mapping.Attributes.UnsavedValueType.Undefined)]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PSEQ", Column = "PSEQ", Type="Decimal")]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PCUST", Column = "PCUST")]
//[NHibernate.Mapping.Attributes.Generator(3, Class="none")]
[NHibernate.Mapping.Attributes.Property(4, Name="PSEQ", Column="PSEQ")]
public virtual decimal PSEQ
{
get
{
return _PSEQ;
}
set
{
if (value != this._PSEQ)
{
_PSEQ = value;
//OnPropertyChanged("PSEQ");
}
}
}
private decimal _PCUST;
//[NHibernate.Mapping.Attributes.Id(0, Column = "PCUST", Type = "Decimal")]
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PCUST
{
get
{
return _PCUST;
}
set
{
if (value != this._PCUST)
{
_PCUST = value;
//OnPropertyChanged("PCUST");
}
}
}
private string _PSTAT;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PSTAT
{
get
{
return _PSTAT;
}
set
{
if (value != this._PSTAT)
{
this._PSTAT = value;
//OnPropertyChanged("PSTAT");
}
}
}
private decimal _PCONO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PCONO
{
get
{
return _PCONO;
}
set
{
if (value != this._PCONO)
{
_PCONO = value;
//OnPropertyChanged("PCONO");
}
}
}
private decimal _PDVNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PDVNO
{
get
{
return _PDVNO;
}
set
{
if (value != this._PDVNO)
{
_PDVNO = value;
//OnPropertyChanged("PDVNO");
}
}
}
private string _PWKTY;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKTY
{
get
{
return _PWKTY;
}
set
{
if (value != this._PWKTY)
{
_PWKTY = value;
//OnPropertyChanged("PWKTY");
}
}
}
private string _PCRTY;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PCRTY
{
get
{
return _PCRTY;
}
set
{
if (value != this._PCRTY)
{
_PCRTY = value;
//OnPropertyChanged("PCRTY");
}
}
}
private decimal _PTSID;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PTSID
{
get
{
return _PTSID;
}
set
{
if (value != this._PTSID)
{
_PTSID = value;
//OnPropertyChanged("PTSID");
}
}
}
private decimal _PCNNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PCNNO
{
get
{
return _PCNNO;
}
set
{
if (value != this._PCNNO)
{
_PCNNO = value;
//OnPropertyChanged("PCNNO");
}
}
}
private decimal _PDTTK;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PDTTK
{
get
{
return _PDTTK;
}
set
{
if (value != this._PDTTK)
{
_PDTTK = value;
//OnPropertyChanged("PDTTK");
}
}
}
private string _PJBNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PJBNO
{
get
{
return _PJBNO;
}
set
{
if (value != this._PJBNO)
{
_PJBNO = value;
//OnPropertyChanged("PJBNO");
}
}
}
private string _PSJNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PSJNO
{
get
{
return _PSJNO;
}
set
{
if (value != this._PSJNO)
{
_PSJNO = value;
//OnPropertyChanged("PSJNO");
}
}
}
private decimal _PTKNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PTKNO
{
get
{
return _PTKNO;
}
set
{
if (value != this._PTKNO)
{
_PTKNO = value;
//OnPropertyChanged("PTKNO");
}
}
}
private string _PCWNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PCWNO
{
get
{
return _PCWNO;
}
set
{
if (value != this._PCWNO)
{
_PCWNO = value;
//OnPropertyChanged("PCWNO");
}
}
}
private string _PWKAR;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKAR
{
get
{
return _PWKAR;
}
set
{
if (value != this._PWKAR)
{
_PWKAR = value;
//OnPropertyChanged("PWKAR");
}
}
}
private string _PWKDC;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKDC
{
get
{
return _PWKDC;
}
set
{
if (value != this._PWKDC)
{
_PWKDC = value;
//OnPropertyChanged("PWKDC");
}
}
}
private string _PWKCD;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKCD
{
get
{
return _PWKCD;
}
set
{
if (value != this._PWKCD)
{
_PWKCD = value;
//OnPropertyChanged("PWKCD");
}
}
}
private string _PCNWO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PCNWO
{
get
{
return _PCNWO;
}
set
{
if (value != this._PCNWO)
{
_PCNWO = value;
//OnPropertyChanged("PCNWO");
}
}
}
private decimal _PWDNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PWDNO
{
get
{
return _PWDNO;
}
set
{
if (value != this._PWDNO)
{
_PWDNO = value;
//OnPropertyChanged("PWDNO");
}
}
}
private string _PDESC;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PDESC
{
get
{
return _PDESC;
}
set
{
if (value != this._PDESC)
{
_PDESC = value;
//OnPropertyChanged("PDESC");
}
}
}
private decimal _PDCCD;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PDCCD
{
get
{
return _PDCCD;
}
set
{
if (value != this._PDCCD)
{
_PDCCD = value;
//OnPropertyChanged("PDCCD");
}
}
}
private decimal _PHRS;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PHRS
{
get
{
return _PHRS;
}
set
{
if (value != this._PHRS)
{
_PHRS = value;
//OnPropertyChanged("PHRS");
}
}
}
private decimal _PUNIT;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PUNIT
{
get
{
return _PUNIT;
}
set
{
if (value != this._PUNIT)
{
_PUNIT = value;
//OnPropertyChanged("PUNIT");
}
}
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
ProddataDAO p = obj as ProddataDAO;
if (this.PCONO == p.PCONO && this.PDVNO == p.PDVNO && this.PCUST == p.PCUST && this.PSEQ == p.PSEQ)
return true;
else
return false;
}
public override int GetHashCode()
{
int hash = 1122;
hash += (null == this.PCONO ? 0 : this.PCONO.GetHashCode());
hash += (null == this.PDVNO ? 0 : this.PDVNO.GetHashCode());
hash += (null == this.PCUST ? 0 : this.PCUST.GetHashCode());
hash += (null == this.PSEQ ? 0 : this.PSEQ.GetHashCode());
return hash;
}
回答1:
One possible cause for this problem is that you have mapped two properties to the same column. For example you have mapped a foreign key relation as a relation and as a property field, or you have a descriminator that you also have mapped as a field.
Looking at the primary key mapping I see that it is mapped twice:
[NHibernate.Mapping.Attributes.CompositeId(1, UnsavedValue=NHibernate.Mapping.Attributes.UnsavedValueType.Undefined)]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PSEQ", Column = "PSEQ", Type="Decimal")]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PCUST", Column = "PCUST")]
//[NHibernate.Mapping.Attributes.Generator(3, Class="none")]
[NHibernate.Mapping.Attributes.Property(4, Name="PSEQ", Column="PSEQ")]
Are you sure this is the way to map a composite key with NHiberante attributes? I haven't used it myself. But my guess is that it is this that is causing NHibernate to think that you have mapped the column PSEQ twice.
I think you should only use the KeyProperty and skip the Property attribute for the properties that belong to the primary key. Try adding this in the top section of the class (do not adorn the property declarations)
[CompositeId(1,UnsavedValue=UnsavedValueType.Undefined)]
[KeyProperty(2, Name="PSEQ", Column="PSEQ")]
[KeyProperty(4, Name="PCUST", Column="PCUST")]
Found this leated forum thread: https://forum.hibernate.org/viewtopic.php?f=25&t=964631&start=0
回答2:
i had a similar situation when using XML mapping, we had originally included the "parent id" column in the .hbm.xml, then when we went to add the back-reference via a many-to-one tag i received the index out of range exception. removing the original declaration was the key.
<class name="IncomeDetail" table="INCOMEDETAILS" mutable="true" lazy="false">
<id name="IncomeDetailID" column="INCOME_DETAIL_ID">
<generator class="native" />
</id>
<property name='ParticipantID' column='PARTICIPANT_ID' type='Int32'/>
<property name='IncomeGroupCD' column='INCOME_GROUP_CD' type='String'/>
<property name='IncomeTypeID' column='INCOME_TYPE_ID' type='Int32'/>
<!--<property name='EmploymentID' column='EMPLOYMENT_ID' type='Int32'/>-->
<property name='IncomeFrequencyCD' column='INCOME_FREQUENCY_CD' type='String'/>
<property name='CapturedDetGrossIncomeAmt' column='CAPTURED_DET_GROSS_INCOME_AMT' type='Decimal'/>
<property name='CapturedDetNetIncomeAmt' column='CAPTURED_DET_NET_INCOME_AMT' type='Decimal'/>
<property name='VerifiedDetGrossIncomeAmt' column='VERIFIED_DET_GROSS_INCOME_AMT' type='Decimal'/>
<property name='VerifiedDetNetIncomeAmt' column='VERIFIED_DET_NET_INCOME_AMT' type='Decimal'/>
<property name='IncomeDesc' column='INCOME_DESC' type='String'/>
<property name='CapturedDT' column='CAPTURED_DT' type='DateTime' not-null='true'/>
<property name='CapturedBy' column='CAPTURED_BY' type='String' not-null='true'/>
<property name='VerificationDT' column='VERIFICATION_DT' type='DateTime' />
<property name='VerifiedBy' column='VERIFIED_BY' type='String' />
<property name='VefificationSourceCD' column='VEFIFICATION_SOURCE_CD' type='String'/>
<many-to-one name="EmploymentIncome" column="EMPLOYMENT_ID" />
</class>
来源:https://stackoverflow.com/questions/1902219/receiving-index-out-of-range-with-nhibernate