如何将新对象添加到IList映射为NHIBnate的一对多?

Jør*_*ode 4 nhibernate one-to-many fluent-nhibernate

我的模型包含一个类Section,该类具有该Statics部分的有序列表.抛弃所有其他属性,模型的实现如下所示:

public class Section
{
    public virtual int Id { get; private set; }
    public virtual IList<Static> Statics { get; private set; }
}

public class Static
{
    public virtual int Id { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

在数据库中,关系实现为一对多,其中表Static 具有指向的外键SectionPosition用于将其索引位置存储在其所属列表中的整数列.

映射是在Fluent NHibernate中完成的,如下所示:

public SectionMap()
{
    Id(x => x.Id);
    HasMany(x => x.Statics).Cascade.All().LazyLoad()
            .AsList(x => x.WithColumn("Position"));
}

public StaticMap()
{
    Id(x => x.Id);
    References(x => x.Section);
}
Run Code Online (Sandbox Code Playgroud)

现在我可以加载现有的Statics,我也可以更新它们的详细信息.但是,我似乎无法找到一种方法来添加新的Statics Section,并将此更改持久保存到数据库中.我尝试了几种组合:

  • mySection.Statics.Add(myStatic)
  • session.Update(mySection)
  • session.Save(myStatic)

但是我得到的最接近的(使用前两个语句)是一个SQL异常读取:"不能将值NULL插入列'Position'".显然INSERT在这里尝试了一个,但NHibernate似乎并没有自动将索引位置附加到SQL语句.

我究竟做错了什么?我在映射中遗漏了什么吗?我是否需要将Position列作为属性公开并自己为其赋值?

编辑:如果我删除数据库中列的NOT NULL约束,显然一切都按预期工作Static.Position.我想NHibernate在用行更新行后立即生成插入Position.

虽然这是问题的答案,但我不确定它是否是最好的.我希望该Position列不可为空,所以我仍然希望有一些方法可以让NHibernate直接在INSERT语句中为该列提供值.

因此,问题仍然存在.还有其他方法吗?

Eri*_*ebo 7

在NHibernate中使用双向一对多关系时,其中一个端点必须是"反向".最佳做法是将集合的结尾设置为反向,因为这样可以避免不必要的SQL语句,并允许id列为"not null".

在文档的第6.4节中,您可以找到以下注释:

非常重要注意:如果关联的列声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束违规.要防止出现此问题,必须使用标记为inverse ="true"的多值结束(集合或包)的双向关联.请参阅本章后面的双向关联讨论.

因此,您需要在SectionMap中将.Inverse()添加到HasMany映射中.

public SectionMap()
{
    Id(x => x.Id);
    HasMany(x => x.Statics)
        .Cascade.All()
        .LazyLoad()
        .Inverse()
        .AsList(x => x.WithColumn("Position"));
}
Run Code Online (Sandbox Code Playgroud)

您可能还需要Section上的Add和Remove方法,它设置/重置静态引用以及向其自己的集合添加/删除静态:

public virtual void AddStatic(Static static)
{
    Statics.Add(static);
    static.Section = this;
}


public virtual void RemoveStatic(Static static)
{
    Statics.Remove(static);
    static.Section = null;
}
Run Code Online (Sandbox Code Playgroud)

这些方法可确保参考文献在关系的两侧保持准确.

根据文档的6.8节,NHibernate在使用索引集合时不支持双向关系:

请注意,NHibernate不支持与索引集合(列表,映射或数组)的双向一对多关联作为"多"端,您必须使用集或包映射.

因此,如果您仍然遇到问题,请考虑使用单向关系而不是双向关系,但这可能意味着您的外键列需要可以为空(根据帖子开头的注释).否则,您可能必须将集合映射为包或集而不是列表.