且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-10-29 23:14:02

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



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

我使用Increment生成的Summary id,以避免从Summary currenty除id以外没有列。



域名:
$ b

  public class详细
{
public int id {get;保护组}
public string ItemName {get;组; }

//重命名为使用Summary.Details映射中指定的相同列名称
public Summary Summary {get; ()









$ b { ;
}

public int id {get;保护组}
public IList< Detail>详情{get;保护组}

映射:

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

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

参考文献< Summary>(x => x.Summary)
//如果你不想重命名Summary,
//你可以这样做相反:
//.TheColumnNameIs(Summary_id)
.CanNotBeNull();
}
}

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

HasMany< Detail>(x => x.Details)
.IsInverse()
.AsBag(); //使用包而不是列表来避免索引更新问题




$ b

Basic question: How to I create a bidirectional one-to-many map in Fluent 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.

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.

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".

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

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.

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.

I made the Summary id generated by increment to avoid problems when inserting into the table since Summary currenty has no columns besides 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
    }
}