简体   繁体   English

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

[英]Fluent NHibernate - how to map a subclass one-to-one?

Suppose I have three classes. 假设我有三个班级。 It is valid to instantiate A, but there are also special cases B and D which subclass A, adding additional information. 实例化A是有效的,但也有特殊情况B和D,它们是A的子类,添加了额外的信息。

How would I do the mapping files for this in (fluent) NHibernate? 我如何在(流畅的)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
}

I tried the following, but it doesn't work at all: 我尝试了以下方法,但它根本不起作用:

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

I'm not sure I understand what you mean by "map a subclass one-to-one", but if you want to map inheritance where the subclasses have properties that are not nullable, you can do like this in Fluent-NHibernate: 我不确定我是通过“映射一对一的子类”来理解你的意思,但如果你想映射继承,其中子类具有不可为空的属性,你可以在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();
    }
}

Since you want the subclasses' properties to be not-null, you have to use the table-per-class (joined-subclass) way of modeling the inheritance. 由于您希望子类的属性不为null,因此必须使用每个类的表(连接子类)方式对继承进行建模。 This is because table-per-hierarchy requires all subclass properties to be nullable. 这是因为每个层次的表要求所有子类属性都可以为空。

I hope it helps. 我希望它有所帮助。

/Erik /埃里克

The syntax may have changed in FNH since Erik's post, but his example is right on target. 自Erik的帖子以来,语法可能在FNH中发生了变化,但他的例子正好在目标上。 Here's some code I used based on Erik's post to work through FNH the two FNH subclass strategies I know of right now (SubClass (the commented out code below, and JoinedSubClass). As an aside, I've seen other names used to describe the same strategies, including in NHibernate docs, which is a bit confusing when this is new to you. ( https://www.hibernate.org/hib_docs/nhibernate/html/inheritance.html ). 以下是我根据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);
        };
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM