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

时间:2021-10-30 11:31:08

Basic question: How to I create a bidirectional one-to-many map in Fluent NHibernate?

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

Details:

细节:

I have a parent object with many children. In my case, it is meaningless for the child to not have a parent, so in the database, I would like the foreign key to the parent to have NOT NULL constraint. I am auto-generating my database from the Fluent NHibernate mapping.

我有很多孩子的父母。在我的例子中,对于没有父类的孩子来说是没有意义的,所以在数据库中,我希望父类的外键没有空约束。我从流畅的NHibernate映射自动生成我的数据库。

I have a parent with many child objects like so:

我的父母有很多这样的孩子:

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

Here is the mapping I started with:

这是我开始的映射:

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

In the Detail table, the Summary_id should be Not Null, because in my case it is meaningless to have a Detail object not attached to the summary object. However, just using the HasMany() map leaves the Summary_id foreign key nullable.

在细节表中,摘要id应该不是Null,因为在我的例子中,没有附加到summary对象的细节对象是没有意义的。然而,只要使用HasMany()映射,就会留下概要的外键nullable。

I found in the NHibernate docs (http://www.hibernate.org/hib_docs/nhibernate/html/collections.html) that "If the parent is required, use a bidirectional one-to-many association".

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

So how do I create the bidirectional one-to-many map in Fluent NHibernate?

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

1 个解决方案

#1


54  

To get a bidirectional association with a not-null foreign key column in the Details table you can add the suggested Owner property, a References(...).CanNotBeNull() mapping in the DetailsMap class, and make the Summary end inverse.

为了在Details表中获得一个非null外键列的双向关联,您可以添加建议的所有者属性、引用(…). cannotbenull()映射在DetailsMap类中,并进行摘要端反。

To avoid having two different foreign key columns for the two association directions, you can either specify the column names manually or name the properties in a way that gives the same column name for both directions. In this case you I suggest renaming the Details.Owner property to Details.Summary.

为了避免为两个关联方向设置两个不同的外键列,您可以手动指定列名,或者以一种为两个方向提供相同的列名的方式命名属性。在这种情况下,我建议重新命名细节。业主财产Details.Summary。

I made the Summary id generated by increment to avoid problems when inserting into the table since Summary currenty has no columns besides id.

为了避免在插入表时出现问题,我生成了增量的摘要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
    }
}

#1


54  

To get a bidirectional association with a not-null foreign key column in the Details table you can add the suggested Owner property, a References(...).CanNotBeNull() mapping in the DetailsMap class, and make the Summary end inverse.

为了在Details表中获得一个非null外键列的双向关联,您可以添加建议的所有者属性、引用(…). cannotbenull()映射在DetailsMap类中,并进行摘要端反。

To avoid having two different foreign key columns for the two association directions, you can either specify the column names manually or name the properties in a way that gives the same column name for both directions. In this case you I suggest renaming the Details.Owner property to Details.Summary.

为了避免为两个关联方向设置两个不同的外键列,您可以手动指定列名,或者以一种为两个方向提供相同的列名的方式命名属性。在这种情况下,我建议重新命名细节。业主财产Details.Summary。

I made the Summary id generated by increment to avoid problems when inserting into the table since Summary currenty has no columns besides id.

为了避免在插入表时出现问题,我生成了增量的摘要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
    }
}