44

基本问题:如何在 Fluent NHibernate 中创建双向一对多映射?

细节:

我有一个有很多孩子的父对象。在我的情况下,孩子没有父母是没有意义的,所以在数据库中,我希望父母的外键有 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 应该为 Not Null,因为在我的情况下,没有附加到摘要对象的 Detail 对象是没有意义的。但是,仅使用 HasMany() 映射会使 Summary_id 外键为空。

我在 NHibernate 文档(http://www.hibernate.org/hib_docs/nhibernate/html/collections.html)中发现“如果需要父级,请使用双向一对多关联”。

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

4

1 回答 1

55

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

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

我制作了增量生成的摘要 ID,以避免插入表时出现问题,因为摘要当前除了 ID 之外没有其他列。

领域:

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

映射:

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
    }
}
于 2008-11-22T09:36:47.347 回答