Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FluentNhibernate Mapping Using References Index Out of Range When Adding new Object

I am trying to map a parent child relationship between a Person object and a Organization object in FluentNHibernate using References in the mapping file like this:

References(x => x.Organization);

The relationship is a Person object contains a OrganizationId column that corresponds to a record in the Organization table with the corresponding OrganizationId. Different Person records can belong to the same Organization.

When I retrieve a Person object it works properly. Person.Organization is populated. I can save a Person object and it works properly. However, when I attempt to add a new Person object I get a Index Out of Range exception from NHibernate. The exception occurs when calling session.SaveOrUpdate(person). I've tried changing the mapping to:

References(x => x.Organization).Cascade.None()

Still get the same error. I can't figure out what is causing the exception. The full exception is this:

System.IndexOutOfRangeException : Invalid index 22 for this SqlParameterCollection with Count=22. 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) at NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd, Object value, Int32 index) at NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, Object value, Int32 index, Boolean[] settable, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id, Object[] fields, Object rowId, Boolean[] includeProperty, Boolean[][] includeColumns, Int32 table, IDbCommand statement, ISessionImplementor session, Int32 index) at NHibernate.Persister.Entity.AbstractEntityPersister.GeneratedIdentifierBinder.BindValues(IDbCommand ps) at NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder) at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session) at NHibernate.Action.EntityIdentityInsertAction.Execute() at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event) at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) at NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event) at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)

like image 253
Jeff Avatar asked Mar 10 '10 17:03

Jeff


1 Answers

First of all the exception occurs because you map the same column twice in your class and that is not allowed. check this IndexOutOfRangeException Deep in the bowels of NHibernate

Secondly (and according to your latest comment) having an OrganizationId and an Organization property in your Person class is sort-of going against the grain. You don't need it. You can access it via per1.Organization.Id

If you already have an Organization in your db (say Id=5) and you map the Organization class to the Person class using the OrganizationId foreign key, then when you code

Organization theOrganizationWithId5 = nhSession.Get<Organization>(5);
per1.Organization = theOrganizationWithId5;
nhSession.Save(per1);

NHibernate will just set the value 5 on the OrganizationId column in your Person table. You will not be populating Organization.

like image 82
Jaguar Avatar answered Oct 23 '22 05:10

Jaguar