首页 文章

流畅的NHibernate:如何创建一对多双向映射?

提问于
浏览
43

Basic question :如何在Fluent NHibernate中创建双向一对多 Map ?

Details:

我有一个有很多孩子的父对象 . 在我的例子中,孩子没有父母是没有意义的,所以在数据库中,我希望父母的外键具有NOT NULL约束 . 我从Fluent NHibernate映射自动生成我的数据库 .

我的父母有很多子对象,如下所示:

public class Summary
{
   public int id {get; protected set;}

   public IList<Detail> Details {get; protected set;}
}

public  class Detail
{
   public int id {get; protected set;}

   public string ItemName {get; set;}

  /* public Summary Owner {get; protected set;} */ //I think this might be needed for bidirectional mapping?
}

这是我开始的映射:

public class SummaryMap : ClassMap<Summary>
{
    public SummaryMap()
    {
        Id(x => x.ID);

        HasMany<Detail>(x => x.Details);
    }
}

public class DetailMap : ClassMap<Detail>
{
    public DetailMap()
    {
        Id(x => x.ID);

        Map(x => x.ItemName).CanNotBeNull();
    }
}

在Detail表中,Summary_id应该不是Null,因为在我的情况下,没有将Detail对象附加到摘要对象是没有意义的 . 但是,只使用HasMany()映射使得Summary_id外键可以为空 .

我在NHibernate docs(http://www.hibernate.org/hib_docs/nhibernate/html/collections.html)中找到了"If the parent is required, use a bidirectional one-to-many association" .

那么如何在Fluent NHibernate中创建双向一对多 Map ?

1 回答

  • 54

    要在Details表中获得与非null外键列的双向关联,您可以在DetailsMap类中添加建议的Owner属性,References(...) . CanNotBeNull()映射,并使Summary结束 .

    要避免为两个关联方向指定两个不同的外键列,可以手动指定列名,也可以为两个方向指定相同列名的方式命名属性 . 在这种情况下,我建议您将Details.Owner属性重命名为Details.Summary .

    我通过增量生成了Summary id,以避免在插入表时出现问题,因为Summary currenty除了id之外没有列 .

    Domain:

    public class Detail
    {
        public int id { get; protected set; }
        public string ItemName { get; set; }
    
        // Renamed to use same column name as specified in the mapping of Summary.Details
        public Summary Summary {get; set;} 
    }
    
    public class Summary
    {
        public Summary()
        {
            Details = new List<Detail>();
        }
    
        public int id { get; protected set; }
        public IList<Detail> Details { get; protected set; }
    }
    

    Mapping:

    public class DetailMap : ClassMap<Detail>
    {
        public DetailMap()
        {
            Id(x => x.id)
                .GeneratedBy.Native();
    
            Map(x => x.ItemName)
                .CanNotBeNull();
    
            References<Summary>(x => x.Summary)
                // If you don't want to rename the property in Summary,
                // you can do this instead:
                // .TheColumnNameIs("Summary_id")
                .CanNotBeNull();
        }
    }
    
    public class SummaryMap : ClassMap<Summary>
    {
        public SummaryMap()
        {
            Id(x => x.id)
                .GeneratedBy.Increment();
    
            HasMany<Detail>(x => x.Details)
                .IsInverse()
                .AsBag(); // Use bag instead of list to avoid index updating issues
        }
    }
    

相关问题