假设我有三个班级。实例化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<A>
{
public AMap()
{
Id(x => x.ID);
Map(x => x.CommonProperty1);
Map(x => x.CommonProperty2);
}
}
public class BMap : ClassMap<B>
{
public BMap()
{
References(x => x.ID);
Map(x => x.BSpecificProperty1)
.CanNotBeNull();
Map(x => x.BSpecificProperty2)
.CanNotBeNull();
}
}
public class DMap : ClassMap<D>
{
public DMap()
{
References(x => x.ID);
Map(x => x.DSpecificProperty)
.CanNotBeNull();
}
}
答案 0 :(得分:7)
我不确定我是通过“映射一对一的子类”来理解你的意思,但如果你想在子类具有不可空的属性的地方映射继承,你可以在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<Animal>
{
public AnimalMap()
{
Id(x => x.Id)
.WithUnsavedValue(0)
.GeneratedBy.Native();
Map(x => x.Name);
var catMap = JoinedSubClass<Cat>("CatId", sm => sm.Map(x => x.Id));
catMap.Map(x => x.WhiskerLength)
.CanNotBeNull();
catMap.Map(x => x.ClawCount)
.CanNotBeNull();
JoinedSubClass<Dog>("DogId", sm => sm.Map(x => x.Id))
.Map(x => x.TailWagRate)
.CanNotBeNull();
}
}
由于您希望子类的属性不为null,因此必须使用每个类的表(连接子类)方式来建模继承。这是因为table-per-hierarchy要求所有子类属性都可以为空。
我希望它有所帮助。
/埃里克
答案 1 :(得分:5)
自Erik的帖子以来,FNH中的语法可能已经改变,但他的例子正好在目标上。以下是我根据Erik的帖子使用的一些代码,用于通过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<Animal>
{
public void Override(AutoMap<Animal> 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<Cat>("CatId", CatMap.AsSubClass())
// .SubClass<Dog>("CatId", DogMap.AsSubClass());
}
}
public class CatMap
{
public static Action<JoinedSubClassPart<Cat>> AsJoinedSubClass()
{
return part =>
{
part.Map(x => x.ClawCount).Not.Nullable();
part.Map(x => x.WhiskerLength).Not.Nullable();
};
}
public static Action<SubClassPart<Cat>> AsSubClass()
{
return part =>
{
part.Map(x => x.ClawCount);
part.Map(x => x.WhiskerLength);
};
}
}
public class DogMap
{
public static Action<JoinedSubClassPart<Dog>> AsJoinedSubClass()
{
return sub =>
{
sub.Map(x => x.TailWagRate).Not.Nullable();
};
}
public static Action<SubClassPart<Dog>> AsSubClass()
{
return sub =>
{
sub.Map(x => x.TailWagRate);
};
}
}
public class BoxerMap
{
public static Action<JoinedSubClassPart<Boxer>> AsJoinedSubClass()
{
return sub =>
{
sub.Map(x => x.DroolBucket);
};
}
public static Action<SubClassPart<Boxer>> AsSubClass()
{
return sub =>
{
sub.Map(x => x.DroolBucket);
};
}
}