Возможно, слишком поздно (вопрос опубликован в 2012 году), но может быть полезным для других, у меня была похожая проблема. Я не использую отображение Fluent, но я использую файлы hbm.
Из того, что я вижу, у вас есть метр, который имеет список показаний. Вы пометили это свойство List как Inverse, что хорошо.
Но, насколько я понимаю, по крайней мере с файлами отображения hbm, вы должны добавить свойство parent к дочернему элементу (чтение в вашем примере), чтобы указывать на родителя (Meter в вашем примере).
Это мой родительский объект (называется Constraint):
<list name="Values" access="field.camelcase-underscore" table="[ConstraintValue]" cascade="all-delete-orphan" inverse="true">
<key column="ConstraintId" not-null="true"/>
<list-index column="OrderId" />
<one-to-many class="ConstraintValue" />
</list>
А это мой дочерний объект (называется Constraint Value):
<!--Parent-->
<many-to-one name="Constraint" access="field.camelcase-underscore" class="Constraint" column="ConstraintId" cascade="merge" not-null="true"/>
И также важно помнить, что в коде нельзя просто добавить дочерний элемент к родителю:
Meter.Readings.Add(newReading);
Вы также должны установить родительское свойство потомка:
newReading.Meter = theParentMeter;
В моем собственном примере у меня есть метод Add в родительском классе, чтобы сделать это для меня (установите свойство коллекции как доступное только для чтения, чтобы заставить пользователей кода вызывать этот метод Add, гарантируя, что родитель всегда набор):
public virtual void AddConstraintValue(ConstraintValue cValue)
{
cValue.Constraint = this;
_values.Add(cValue);
}
Возвращаясь к первоначальному вопросу, я обновил Nhibernate 2.2 напрямую до NH 3.3.3.4001 и начал получать сообщение об ошибке «Неверный индекс n для этой коллекции SqlParameterCollection с Count = n». Я отладил исходный код NH и обнаружил, что метод Dehydrate AbstractEntityPersister просматривает свойства и устанавливает их для команды sql @ p0, @ p1 и т. Д., А затем добавляет Id в качестве последнего параметра. Я использую Hilo ID Generation, поэтому ID известен заранее.
Изначально у меня не было inverse = true на родительской стороне.
Дегидрат пытался установить команду sql:
INSERT INTO [ConstraintValue] (ParameterId, Value, ConstraintId, OrderId, Id) VALUES (@p0, @p1, @p2, @p3, @p4)
но каким-то образом @ p0 и @ p3 были установлены на один и тот же hilo Id, я ожидал, что @ p3 будет «порядком» списка (число типа 0, 1 или 2), а затем он попытается установить фактический идентификатор объекта, как индекс = 5, и я получаю исключение.
Затем я наконец-то понял, что пропустил inverse = true , и после исправления получил команду sql в Dehydrate:
INSERT INTO [ConstraintValue] (ConstraintId, ParameterId, Value, Id) VALUES (@p0, @p1, @p2, @p3)
И на этот раз в массиве свойств было только 3 свойства (@ p0, @ p1 и @ p2), «OrderId» даже нигде не упоминается на данном этапе. Эти 3 свойства задаются в цикле for в Dehydrate, а затем после этого для идентификатора @ p3 устанавливается идентификатор объекта с помощью IdentifierType.NullSafeSet сразу после цикла for.
Подводя итог, я получил это исключение не потому, что дважды сопоставил один и тот же столбец или свойство, а потому, что у меня были родительские / дочерние отношения без обратного = true для родителя.