Nhibernate ComposedId在中间表上

时间:2015-02-04 10:37:29

标签: c# sql-server nhibernate

我想要一个只有两个外键的中间表(作为ComposedId)。 但NHibernate会自动创建一个" id"属性。

我有以下课程

public class Lace
{
    public virtual int Id { get; set; }
    public virtual string Hostname { get; set; }

    public virtual IList<LaceHasCard> LaceHasCards { get; set; }
}

public class Card
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }

    public virtual IList<LaceHasCard> LaceHasCards { get; set; }
}

并手动创建中间表

public class LaceHasCard
{
    public virtual Card Card { get; set; }
    public virtual Lace Lace { get; set; }
}

映射

public LaceMapping()
{
    Id(x => x.Id, map => map.Generator(Generators.Native));
    Property(x => x.Hostname);

    Bag(x => x.LaceHasCards, col =>
    {
        col.Key(k => k.Column("LaceId"));
        col.Inverse(true);
    }, r => r.OneToMany());
}

public CardMapping()
{
    Id(x => x.Id, map => map.Generator(Generators.Native));
    Property(x => x.Name);

    Bag(x => x.LaceHasCards, col =>
    {
        col.Key(k => k.Column("CardId"));
        col.Inverse(true);
    }, r => r.OneToMany());
}

中间表映射

public LaceHasCardMapping()
{
    //ComposedId(map =>
    //{
    //    map.Property(x => x.Card.Id, a =>
    //    {
    //        a.Column("CardId");
    //    });
    //    map.Property(x => x.Lace.Id, a =>
    //    {
    //        a.Column("LaceId");
    //    });
    //});

    ManyToOne(x => x.Card, map =>
    {
        map.Column("CardId");
    });

    ManyToOne(x => x.Lace, map =>
    {
        map.Column("LaceId");
    });
}

如果我使用ComposedId注释掉创建架构,NHibernate将创建一个&#34; id&#34;表中的财产。

CREATE TABLE [dbo].[LaceHasCard] (
    [id]     INT NOT NULL,
    [CardId] INT NULL,
    [LaceId] INT NULL,
    PRIMARY KEY CLUSTERED ([id] ASC),
    CONSTRAINT [FKDC6D54711CD160AE] FOREIGN KEY ([CardId]) REFERENCES [dbo].[Card] ([Id]),
    CONSTRAINT [FKDC6D547151F8AF85] FOREIGN KEY ([LaceId]) REFERENCES [dbo].[Lace] ([Id])
);

如果我尝试使用ComposedId创建架构,则会收到以下错误消息:

  

无法实例化映射类(请参阅InnerException):   EmpLaceMgmt.Models.Mappings.LaceHasCardMapping

告诉NHibernate创建一个合成ID的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

让我给你一些建议,只是我的观点 - 不要使用复合ID。在DB中使用标准主键,并将其C#/实体表示用作Id { get; set; }

Chapter 24. Best Practices

  

...

     

声明持久化类的标识符属性。

     

NHibernate使标识符属性可选。你应该使用它们有各种各样的原因。 我们建议标识符为“合成”标识符。 (生成,没有商业意义)和非基本类型。为获得最大的灵活性,请使用Int64或String。

另请参阅wiki上的synthetic, surrogate keys

根据我的经验,我们不应该担心这样的配对对象:

public class LaceHasCard
{
    public virtual int Id { get; set; } // the key
    public virtual Card Card { get; set; }
    public virtual Lace Lace { get; set; }
}

因为稍后它会变得如此容易访问它:

session.Get<LaceHasCard>(id)

并在Subqueries 中使用它(用于过滤带花边的卡片,反之亦然)

自动生成的DB中的一列不应该有任何额外的不良影响。但处理这样的表有点(很多)更容易......

所以,总结一下,我的建议是,让所有实体成为一级公民,拥有完整的权利(包括合成/代理键)

相关问题