I have the following mappings:
public class SecurityMap : ClassMap<Security>
{
public SecurityMap()
{
Table("Security");
CompositeId().KeyProperty(k => k.Id, "SecurityId").KeyProperty(k => k.EndDate);
Map(x => x.LastUpdateUser);
References(x => x.Company).Columns("CompanyId", "EndDate");
References(x => x.PrimaryListing).Columns("PrimaryListingId", "EndDate");
}
}
public class ListingMap : ClassMap<Listing>
{
public ListingMap()
{
Table("Listing");
CompositeId().KeyProperty(k => k.Id, "ListingID").KeyProperty(k => k.EndDate);
References(x => x.Security).Columns("SecurityId","EndDate");
}
}
public class CompanyMap : ClassMap<Company>
{
public CompanyMap()
{
Table("Company");
CompositeId().KeyProperty(k => k.Id, "CompanyID").KeyProperty(k => k.EndDate);
HasMany(x => x.Securities).KeyColumns.Add("CompanyId", "EndDate");
}
}
When I attempt to run this test:
[Test]
public void can_update_a_security()
{
var repo = IoC.Resolve<ISecurityRepository>();
int someSecurity = 1;
using (var work = IoC.Resolve<IUnitOfWorkManager>().Current)
{
Security security = repo.Get(someSecurity);
security.ShouldNotBeNull();
security.LastUpdateUser = "Dirk Diggler" + DateTime.Now.Ticks;
repo.Save(security);
work.Commit();
}
}
I get the following error deep in the bowels of NHibernate:
Execute
System.IndexOutOfRangeException: Invalid index 6 for this
SqlParameterCollection with Count=6.
at System.Data.SqlClient.SqlParameterCollection.RangeCheck(Int32
index)
at System.Data.SqlClient.SqlParameterCollection.GetParameter(Int32
index)
at System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item(Int32
index)
s:\NHibernate\NHibernate\src\NHibernate\Type\DateTimeType.cs(65,0):
at
NHibernate.Type.DateTimeType.Set(IDbCommand
st, Object value, Int32 index)
s:\NHibernate\NHibernate\src\NHibernate\Type\NullableType.cs(180,0):
at
NHibernate.Type.NullableType.NullSafeSet(IDbCommand
cmd, Object value, Int32 index)
s:\NHibernate\NHibernate\src\NHibernate\Type\NullableType.cs(139,0):
at
NHibernate.Type.NullableType.NullSafeSet(IDbCommand
st, Object value, Int32 index,
ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Type\ComponentType.cs(213,0):
at
NHibernate.Type.ComponentType.NullSafeSet(IDbCommand
st, Object value, Int32 begin,
ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2393,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object
id, Object[] fields, Object rowId,
Boolean[] includeProperty, Boolean[][]
includeColumns, Int32 table,
IDbCommand statement,
ISessionImplementor session, Int32
index)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2754,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object
id, Object[] fields, Object[]
oldFields, Object rowId, Boolean[]
includeProperty, Int32 j, Object
oldVersion, Object obj, SqlCommandInfo
sql, ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2666,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object
id, Object[] fields, Object[]
oldFields, Object rowId, Boolean[]
includeProperty, Int32 j, Object
oldVersion, Object obj, SqlCommandInfo
sql, ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2940,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object
id, Object[] fields, Int32[]
dirtyFields, Boolean
hasDirtyCollection, Object[]
oldFields, Object oldVersion, Object
obj, Object rowId, ISessionImplementor
session)
s:\NHibernate\NHibernate\src\NHibernate\Action\EntityUpdateAction.cs(78,0):
at
NHibernate.Action.EntityUpdateAction.Execute()
s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(130,0):
at
NHibernate.Engine.ActionQueue.Execute(IExecutable
executable)
s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(113,0):
at
NHibernate.Engine.ActionQueue.ExecuteActions(IList
list)
s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(147,0):
at
NHibernate.Engine.ActionQueue.ExecuteActions()
s:\NHibernate\NHibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs(241,0):
at
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource
session)
s:\NHibernate\NHibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs(19,0):
at
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent
event)
s:\NHibernate\NHibernate\src\NHibernate\Impl\SessionImpl.cs(1478,0):
at NHibernate.Impl.SessionImpl.Flush()
s:\NHibernate\NHibernate\src\NHibernate\Transaction\AdoTransaction.cs(187,0):
at
NHibernate.Transaction.AdoTransaction.Commit()
at lambda_method(ExecutionScope , ITransaction )
Now the interesting thing is if I comment out the reference to Company or PrimaryListing in the SecurityMap, I don’t get the error. It doesn’t seem to matter which I comment out. The error only happens when I have both.
When the update actually goes through NHProf shows me this update:
UPDATE Security
SET LastUpdateUser = '2010-02-19T08:09:24.00' /* @p0 */,
CompanyId = 54199 /* @p1 */,
EndDate = '9999-12-31T00:00:00.00' /* @p2 */
WHERE SecurityId = 1 /* @p3 */
AND EndDate = '9999-12-31T00:00:00.00' /* @p4 */
I am not sure why it is updating CompanyId and EndDate, but I suspect it is related.
Any one have ideas? Work arounds would be greatly appreciated.
Yes its a common problem, you are using the
Column "EndDate"twice in your mapping definition (for both Company and PrimaryListing) and that is not allowed. One of them has to go, or have an additional EndDate column (one for each association)check this too
nHibernate 2.0 – mapping a composite-id *and* many-to-one relationship causes "invalid index" error
and
http://devlicio.us/blogs/derik_whittaker/archive/2009/03/19/nhibernate-and-invalid-index-n-for-this-sqlparametercollection-with-count-n-error.aspx