首页 文章

Nhibernate ComposedId在中间表上

提问于
浏览
1

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

I have the following classes

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

Mappings

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将在表中创建一个“id”属性 .

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 回答

  • 1

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

    第24章最佳实践

    ...声明持久化类的标识符属性 . 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中的一列不应该有任何额外的不良影响 . 但处理这样的表有点(很多)更容易......

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

相关问题