IndexOutOfRangeException Глубоко в недрах NHibernate

У меня есть следующие сопоставления:

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");
        }       
    }

Когда я пытаюсь запустить этот тест:

[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();
    }
}

Глубоко в недрах NHibernate я получаю следующую ошибку:

Теперь интересно то, что если я закомментирую ссылку на Company или PrimaryListing в SecurityMap, я не получаю сообщение об ошибке. Кажется, не имеет значения, что я комментирую. Ошибка возникает только тогда, когда у меня есть оба.

Когда обновление действительно проходит через NHProf, я вижу это обновление:

Я не уверен, почему он обновляет CompanyId и EndDate, но подозреваю, что это связано.

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 */

У кого-нибудь есть идеи? Работа вокруг будет принята с благодарностью.

Да, это обычная проблема, вы дважды используете

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");
        }       
    }
в определении сопоставления (как для компании, так и для первичного списка), и это недопустимо. Один из них должен уйти или иметь дополнительный столбец EndDate (по одному для каждой ассоциации)


person NotMyself    schedule 19.02.2010    source источник
comment
Индекс был вне допустимого диапазона. Должен быть неотрицательным и быть меньше размера коллекции.   -  person NotMyself    schedule 25.02.2010
comment
Вы знаете, будет ли это в конечном итоге исправлено? Это делает NH непригодным для более сложных сценариев, связанных с секционированными таблицами ...   -  person Daniel Little    schedule 07.01.2011


Ответы (1)


проверьте это тоже nHibernate 2.0 - сопоставление отношения составного идентификатора * и * многие-к-одному вызывает недопустимую ошибку индекса

и http://devlicio.us/blogs/derik_whittaker/archive/2009/03/19/nhibernate-and-invalid-index-n-for-this-sqlparametercollection-with-count-n-error.aspx

надеясь, что кто-то другой может добавить предложения по обходным путям.

person Jaguar    schedule 22.02.2010
comment
Похоже, это все еще проблема даже с NH 4.0. - person Daniel Hilgarth; 07.03.2012
comment
@LeoHernandez, это не проблема. Для всех намерений и целей, если вы хотите использовать один столбец для нескольких свойств, вы делаете это неправильно. - person leojh; 18.12.2014
comment
@Jaguar Я согласен с вами, за исключением того, что я столкнулся со сценарием, в котором одно из полей составного ключа используется как FK для другого составного ключа. При сопоставлении Composite Id снова для FK NH выдает эту ошибку. NH не следует рассматривать поля, отображаемые как часть составного ключа, как повторяющиеся в этом сценарии. Опять же, это испорченная устаревшая база данных, и вы не можете ожидать, что она все сделает. Я пришел к хорошему компромиссу. - person Jaguar; 18.12.2014
comment
@LeoHernandez ах да, я думаю, это верный сценарий - person leojh; 19.12.2014
comment
Выполните System.IndexOutOfRangeException: недопустимый индекс 6 для этой коллекции SqlParameterCollection с Count = 6. в System.Data.SqlClient.SqlParameterCollection.RangeCheck (индекс Int32) в System.Data.SqlClient.SqlParameterCollection.GetParameter (индекс Int32) в System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item (индекс Int32) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Type \ DateTimeType.cs (65,0): в NHibernate.Type.DateTimeType.Set (IDbCommand st, значение объекта, индекс Int32) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Type \ NullableType.cs (180,0): в NHibernate.Type.NullableType.NullSafeSet (IDbCommand cmd, значение объекта, индекс Int32) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Type \ NullableType.cs (139,0): в NHibernate.Type.NullableType.NullSafeSet (IDbCommand st, значение объекта, индекс Int32, сеанс ISessionImplementor) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Type \ ComponentType.cs (213,0): в NHibernate.Type.ComponentType. NullSafeSet (IDbCommand st, значение объекта, начало Int32, сеанс ISessionImplementor) s: \ NHibernate \ N Hibernate \ src \ NHibernate \ Persister \ Entity \ AbstractEntityPersister.cs (2393,0): в NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (Object id, Object [] fields, Object rowId, Boolean [] includeProperty, Boolean [] [ ] includeColumns, таблица Int32, оператор IDbCommand, сеанс ISessionImplementor, индекс Int32) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Persister \ Entity \ AbstractEntityPersister.cs (2754,0): в NHibernate.Persister.Entity.AbstractEntityPersister.Update ( Идентификатор объекта, поля Object [], 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): в NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert (Object id, Object [] fields, Object [] oldFields, Object rowId, Boolean [] includeProperty, Int32 j, Object oldVersion, Object obj , SqlC ommandInfo sql, сеанс ISessionImplementor) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Persister \ Entity \ AbstractEntityPersister.cs (2940,0): в 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): в NHibernate. Action.EntityUpdateAction.Execute () s: \ NHibernate \ NHibernate \ src \ NHibernate \ Engine \ ActionQueue.cs (130,0): в NHibernate.Engine.ActionQueue.Execute (исполняемый файл IExecutable) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Engine \ ActionQueue.cs (113,0): в NHibernate.Engine.ActionQueue.ExecuteActions (список IList) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Engine \ ActionQueue.cs (147,0): в NHibernate. Engine.ActionQueue.ExecuteActions () s: \ NHibernate \ NHibernate \ src \ NHibernate \ Event \ Default \ AbstractFlushingEventListener.cs (241,0): в NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions (сеанс IEventSourcenate) NHibernate \ src \ NHibernate \ Event \ Default \ DefaultFlushEventListener.cs (19,0): в NHibernate.Event.Default.DefaultFlushEventListener.OnFlush (событие FlushEvent) s: \ NHibernate \ NHibernate \ src \ NHibernate \ Impl \ SessionImpl.cs ( 1478,0): в NHibernate.Impl.SessionImpl.Flush () s: \ NHibernate \ NHibernate \ src \ NHibern ate \ Transaction \ AdoTransaction.cs (187,0): в NHibernate.Transaction.AdoTransaction.Commit () в lambda_method (ExecutionScope, ITransaction) - person Jaguar; 29.12.2014