我想要一个只有两个外键的中间表(作为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的正确方法是什么?
答案 0 :(得分:1)
让我给你一些建议,只是我的观点 - 不要使用复合ID。在DB中使用标准主键,并将其C#/实体表示用作Id { get; set; }
...
声明持久化类的标识符属性。
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中的一列不应该有任何额外的不良影响。但处理这样的表有点(很多)更容易......
所以,总结一下,我的建议是,让所有实体成为一级公民,拥有完整的权利(包括合成/代理键)