流畅的NHibernate – 如何一对一地映射子类?

假设我有三个class级。 实例化A是有效的,但也有特殊情况B和D,它们是A的子类,添加了额外的信息。

我如何在(流畅的)NHibernate中为此创建映射文件?

public class A { public int ID { get; set;} public string CommonProperty1 { get; set; } public string CommonProperty2 { get; set; } } public class B : A { public string BSpecificProperty1 { get; set; } //not null public string BSpecificProperty2 { get; set; } //not null } public class D : A { public string DSpecificProperty { get; set; } //not null } 

我尝试了以下内容,但它根本不起作用:

 public class AMap : ClassMap { public AMap() { Id(x => x.ID); Map(x => x.CommonProperty1); Map(x => x.CommonProperty2); } } public class BMap : ClassMap { public BMap() { References(x => x.ID); Map(x => x.BSpecificProperty1) .CanNotBeNull(); Map(x => x.BSpecificProperty2) .CanNotBeNull(); } } public class DMap : ClassMap { public DMap() { References(x => x.ID); Map(x => x.DSpecificProperty) .CanNotBeNull(); } } 

我不确定我是通过“映射一对一的子类”来理解你的意思,但如果你想映射inheritance,其中子类具有不可为空的属性,你可以在Fluent-NHibernate中这样做:

 // Domain classes public class Animal { public virtual int Id { get; set; } public virtual string Name { get; set; } } public class Cat : Animal { public virtual int WhiskerLength { get; set; } public virtual int ClawCount { get; set; } } public class Dog : Animal { public virtual int TailWagRate { get; set; } } // Mapping file public class AnimalMap : ClassMap { public AnimalMap() { Id(x => x.Id) .WithUnsavedValue(0) .GeneratedBy.Native(); Map(x => x.Name); var catMap = JoinedSubClass("CatId", sm => sm.Map(x => x.Id)); catMap.Map(x => x.WhiskerLength) .CanNotBeNull(); catMap.Map(x => x.ClawCount) .CanNotBeNull(); JoinedSubClass("DogId", sm => sm.Map(x => x.Id)) .Map(x => x.TailWagRate) .CanNotBeNull(); } } 

由于您希望子类的属性不为null,因此必须使用每个类的表(连接子类)方式对inheritance进行建模。 这是因为table-per-hierarchy要求所有子类属性都可以为空。

我希望它有所帮助。

/埃里克

自Erik的post以来,语法可能在FNH中发生了变化,但他的例子正好在目标上。 这里是我根据Erik的post使用的一些代码,用于通过FNH处理我现在知道的两个FNH子类策略(SubClass(下面注释掉的代码和JoinedSubClass)。顺便说一下,我看过用于描述其他名称的其他名称相同的策略,包括在NHibernate文档中,当这对你来说是新的时候会有点混乱。( https://www.hibernate.org/hib_docs/nhibernate/html/inheritance.html )。

 // Domain classes public class Animal : Entity { public virtual string Name { get; set; } public virtual string Unwanted { get; set; } } public class Cat : Animal { public virtual int WhiskerLength { get; set; } public virtual int ClawCount { get; set; } } public class Dog : Animal { public virtual int TailWagRate { get; set; } } public class Boxer : Dog { public string DroolBucket { get; set; } } public class AnimalMapJoinedSubclassOverride : IAutoMappingOverride { public void Override(AutoMap mapping) { mapping.Map(x => x.Name); mapping.IgnoreProperty(x => x.Unwanted); mapping.JoinedSubClass("CatId", CatMap.AsJoinedSubClass()); mapping.JoinedSubClass("DogId", DogMap.AsJoinedSubClass()); //mapping.DiscriminateSubClassesOnColumn("Type") // .SubClass("CatId", CatMap.AsSubClass()) // .SubClass("CatId", DogMap.AsSubClass()); } } public class CatMap { public static Action> AsJoinedSubClass() { return part => { part.Map(x => x.ClawCount).Not.Nullable(); part.Map(x => x.WhiskerLength).Not.Nullable(); }; } public static Action> AsSubClass() { return part => { part.Map(x => x.ClawCount); part.Map(x => x.WhiskerLength); }; } } public class DogMap { public static Action> AsJoinedSubClass() { return sub => { sub.Map(x => x.TailWagRate).Not.Nullable(); }; } public static Action> AsSubClass() { return sub => { sub.Map(x => x.TailWagRate); }; } } public class BoxerMap { public static Action> AsJoinedSubClass() { return sub => { sub.Map(x => x.DroolBucket); }; } public static Action> AsSubClass() { return sub => { sub.Map(x => x.DroolBucket); }; } }