C# 中间表上的Nhibernate ComposeId

C# 中间表上的Nhibernate ComposeId,c#,sql-server,nhibernate,C#,Sql Server,Nhibernate,我想要一个只有两个外键的中间表(作为ComposeId)。 但是NHibernate会自动创建一个“id”属性 我有以下课程 public class Lace { public virtual int Id { get; set; } public virtual string Hostname { get; set; } public virtual IList<LaceHasCard> LaceHasCards { get; set; } } pub

我想要一个只有两个外键的中间表(作为ComposeId)。 但是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 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 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 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])
);
如果尝试使用ComposeId创建架构,则会收到以下错误消息:

无法实例化映射类(请参阅InnerException): 安放管理.Models.Mappings.LaceHasCardMapping


告诉NHibernate创建复合Id的正确方法是什么?

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

声明持久类的标识符属性。 NHibernate使标识符属性成为可选的。你应该使用它们有各种各样的理由我们建议标识符是“合成的”(生成的,没有业务意义),并且是非原语类型。要获得最大的灵活性,请使用Int64或字符串。

另请参见关于wiki的更多信息

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

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)
session.Get(id)
也可在
子查询中使用它(用于过滤带花边的卡片,反之亦然)

DB中自动生成的一列不应有任何额外的不良影响。但是处理这样的表格要容易一点


总之,我的建议是,让所有实体都成为一级公民,拥有完全的权利(包括合成/代理密钥)

尽管有你的问题,我自己的建议是-使用其他方法来解决它。不要使用复合键。提供具有自己ID的配对对象。使其成为一级公民。稍后,您将获得奖励,一旦您将开始查询。。。其中一列带有自动生成的代理键,不应损害任何性能。但NHiberante将提供更容易的处理。。。这只是我个人的建议。你的意思是我应该像所有其他表一样,在中间表中添加一个Id属性,并自动递增?我100%使用这种方法。(无多对多-每个对象,包括配对为第一级===具有ID,具有代理ID列…)都将带来好处。。。但这是我的方式。也许其他人会提出不同的建议。在极端情况下(这经常发生在用户身上),可以提供由“配对对象”驱动的视图。。。那么它很方便,它确实包含一个ID,因为NHibernate可以提供简化的处理……代理ID列是什么意思?这与普通主键相同吗?是的,代理键的意思是“它没有业务意义”,即它只是与DB相关的东西(和NHibernate;),我如何在您的建议中向中间表添加数据?看:我试着给你我最好的想法。。。希望能有帮助