流利的NHibernate - IndexOutOfRange

时间:2012-05-21 16:35:19

标签: nhibernate fluent-nhibernate fluent-nhibernate-mapping nhibernate-3

我已经阅读了所有帖子,并且知道IndexOutOfRange通常会发生,因为列被引用了两次。但我根据我的映射看不出这是怎么回事。如果配置中的SHOW_SQL为true,我会在Events表中看到一个Insert,然后在IndexOutOfRangeException表中看到RadioButtonQuestions。我看不到它试图使用的SQL会产生异常。我尝试使用AutoMapping,现在已经为这两个类切换到完整ClassMap,以尝试缩小问题范围。

public class RadioButtonQuestion : Entity
{
    [Required]
    public virtual Event Event { get; protected internal set; }

    [Required]
    public virtual string GroupIntroText { get; set; }
}

public class Event : Entity
{
    [Required]
    public virtual string Title { get; set; }

    [Required]
    public virtual DateTime EventDate { get; set; }

    public virtual IList<RadioButtonQuestions> RadioButtonQuestions { get; protected internal set; }
}




public class RadioButtonQuestionMap : ClassMap<RadioButtonQuestion>
{
    public RadioButtonQuestionMap()
    {
        Table("RadioButtonQuestions");

        Id(x => x.Id).Column("RadioButtonQuestionId").GeneratedBy.Identity();

        Map(x => x.GroupIntroText);
        References(x => x.Event).Not.Nullable();
    }
}


public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Id(x => x.Id).Column("EventId").GeneratedBy.Identity();
        Map(x => x.EventDate);
        Map(x => x.Title);
        HasMany(x => x.RadioButtonQuestions).AsList(x => x.Column("ListIndex")).KeyColumn("EventId").Not.Inverse().Cascade.AllDeleteOrphan().Not.KeyNullable();
    }
}

生成的SQL看起来正确:

create table Events (
    EventId INT IDENTITY NOT NULL,
   EventDate DATETIME not null,
   Title NVARCHAR(255) not null,
   primary key (EventId)
)

create table RadioButtonQuestions (
    RadioButtonQuestionId INT IDENTITY NOT NULL,
   GroupIntroText NVARCHAR(255) not null,
   EventId INT not null,
   ListIndex INT null,
   primary key (RadioButtonQuestionId)
)

这是使用NH 3.3.0.4000和FNH 1.3.0.727。当我尝试保存一个新事件(附加了RadioButtonQuestion)时,我看到了

NHibernate:INSERT INTO事件(EventDate,Title)VALUES(@ p0,@ p1); @ p0 = 5/21/2012 12:32:11 PM [类型:日期时间(0)],@ p1 ='我的测试事件'[类型:字符串(0)] NHibernate:选择@@ IDENTITY

Events.Tests.Events.Tasks.EventTasksTests.CanCreateEvent: NHibernate.PropertyValueException:使Events.Domain.RadioButtonQuestion._Events.Domain.Event.RadioButtonQuestionsIndexBackref的属性值脱水错误   ----&GT; System.IndexOutOfRangeException:此SqlCeParameterCollection不包含带有ParameterIndex“3”的SqlCeParameter。

因此,如果一个列确实被引用两次,那么我的FNH配置导致该行为的问题是什么?我正在尝试订购双向关系(一个事件有许多单选按钮问题)(我会维护它,因为NH不会与我读过的双向关系)。 FWIW我也尝试将此作为单向关系,从Event移除RadioButtonQuestion,但仍然会导致相同的异常。

3 个答案:

答案 0 :(得分:6)

我在代码中使用映射(NH 3.3.1),我注意到添加Update(false)和Insert(false)可以解决问题:

ManyToOne(x => x.DictionaryEntity, map =>
{
    map.Column("Dictionary");
    map.Update(false);
    map.Insert(false);
    map.Cascade(Cascade.None);
    map.Fetch(FetchKind.Select);
    map.NotFound(NotFoundMode.Exception);
    map.Lazy(LazyRelation.Proxy);
});

答案 1 :(得分:4)

您有一个双向关联,因此一方应标记为Inverse(),并且只能是RadioButtonQuestions集合。如果您希望集合成为所有者,则必须删除RadioButtonQuestion类中对事件的引用。

此外,表RadioButtonQuestions中的EventId列不可为空,如果集合映射不是反向的,则可能导致问题。请参阅文档中的note

答案 2 :(得分:0)

我刚刚花了一个上午来根除此错误。 IndexOutOfRangeException最初使我走错了路,但我找到了原因。 我的问题与使用多个组件的FluentNHibernate类映射有关。问题在于,两个属性被无意间错误地映射到同一列:

之前:

// example is stripped for simplicity, note the column names
Component(mappedClass => mappedClass.MappedComponent1,
          map => 
          {
              map.Map(c => c.SomeProperty, "samecolumn");
          });

Component(mappedClass => mappedClass.MappedComponent2,
          map => 
          {
              map.Map(c => c.OtherProperty, "samecolumn");
          });

之后:

Component(mappedClass => mappedClass.MappedComponent1,
          map => 
          {
              map.Map(c => c.SomeProperty, "firstcolumn");
          });

Component(mappedClass => mappedClass.MappedComponent2,
          map => 
          {
              map.Map(c => c.OtherProperty, "secondcolumn");
          });

这对IndexOutOfRangeException造成的影响对我来说并不明显;我猜这里有一个映射的(源)属性数组和一个目标列数组,在这种情况下,目标数组对于源属性数组中的项目数来说太短了,因为某些目标列是相同的

我认为,但值得为FluentNHibernate编写拉取请求以检查此情况并引发更明确的异常。