代码之家  ›  专栏  ›  技术社区  ›  Jørn Schou-Rode dscher

如何向使用NHibernate映射为一对多的IList添加新对象?

  •  4
  • Jørn Schou-Rode dscher  · 技术社区  · 17 年前

    我的模型包含一个类 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; }
    }
    

    Static 有一个外键指向 部分 Position 将其索引位置存储在它所属的列表中。

    映射在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);
    }
    

    现在我可以加载现有的 静止的 静止的 a:是的 ,并将此更改保留到数据库中。我尝试了以下几种组合:

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

    INSERT 在这里尝试,但NHibernate似乎不会自动将索引位置附加到SQL语句。

    我做错了什么?我的映射中是否缺少某些内容?我需要把照片曝光吗 位置 列作为属性并自己为其赋值?

    编辑: 很明显,如果我移除 NOT NULL Static.Position 数据库中的列。我猜NHibernate进行了插入,并在使用 位置 价值

    虽然这是问题的答案,但我不确定这是否是最好的答案。我更喜欢 位置 列不可为null,所以我仍然希望有某种方法可以使NHibernate直接在 插入 陈述

    因此,问题仍然悬而未决。还有其他解决办法吗?

    3 回复  |  直到 17 年前
        1
  •  7
  •   Jørn Schou-Rode dscher    16 年前

    在NHibernate中使用双向一对多关系时,一端必须为“反向”。最佳实践是将集合的结尾设置为反向,因为这样可以避免不必要的SQL语句,并允许id列为“NOTNULL”。

    在里面 section 6.4

    非常重要的注意:如果关联的列被声明为NOTNULL,那么NHibernate在创建或更新关联时可能会导致违反约束。为了防止此问题,必须使用双向关联,将多值端(集合或包)标记为reverse=“true”。请参阅本章后面关于双向关联的讨论。

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

    您可能还希望在节上使用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;
    }
    

    根据 section 6.8

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

    所以,如果你仍然有麻烦,考虑使用单向关系而不是双向的,但是这可能意味着你的外键列需要是空的(根据文章开头的注释)。否则,您可能需要将您的收藏映射为一个包或一套,而不是一个列表。

        2
  •  2
  •   twk    17 年前

    在Static的表中有一个名为“SectionID”或类似字段。 让此字段为空:NHibernate首先添加新记录,然后更新引用的id。

    我在我的数据库中发现了这一点,我也很惊讶:为什么NH不喜欢数据库级别的正确表引用?

        3
  •  1
  •   Rob Gray    13 年前

    在你的解决方案中,你就快到了。HasMany的映射是正确的。问题是,正如您所说,位置在数据库中没有得到更新(FWIW当您将其设置为null时,它只“起作用”,因为null被插入到数据库中;对我来说,这实际上不起作用;))。

    public virtual int Position 
    {
        get 
        {
            // Will throw exception if Section is null
            // or Section.Statics is null...
            return Section.Statics.IndexOf(this);
        }
        protected set 
        {
        }
    }
    

    在db中的Position列中的位置将被更新(记住在StaticMap中映射您的位置)。