Fluent NHibernate Inheritance mapping type

2019-05-30 17:45发布

问题:

I'm new to Fluent NHibernate, thus far I managed to get my mapping working except for the inheritance part. Is there anybody who could help me finish the mapping? I have simplified the code as much as possible.

Thank you!

My database:

CREATE TABLE [User] (
UserID                  INT             NOT NULL IDENTITY(1,1),
Type                    CHAR(1)         NOT NULL,
Email                   VARCHAR(255)    NOT NULL,
PRIMARY KEY(UserID)
);

CREATE TABLE [Student] (
UserID                  INT             NOT NULL,
Firstname               VARCHAR(255)    NOT NULL,
PRIMARY KEY(UserID),
FOREIGN KEY(UserID) REFERENCES [User](UserID)               
);

CREATE TABLE [Company] (
UserID                  INT             NOT NULL,
Name                    VARCHAR(255)    NOT NULL,
PRIMARY KEY(UserID),
FOREIGN KEY(UserID) REFERENCES [User](UserID),
);

My classes:

public class User
{
    public virtual int UserID { get; set; }
    public virtual UserType Type { get; set; }
    public virtual string Email { get; set; }
    public User()
    {
    }
}

public class Student : User
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public Student() 
        : base()
    {

    }
}

public class Company : User
{
    public virtual string Name { get; set; }
    public Company() 
        : base()
    {
    }
}

public enum UserType
{
    STUDENT = 0,
    COMPANY = 1
}

Mapping:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Table("[User]");
        Id(x => x.UserID);
        Map(x => x.Type).CustomType<int>();
        Map(x => x.Email);
    }
}

public class CompanyMap : ClassMap<Company>
{
    public CompanyMap()
    {
        Table("Company");
        Id(x => x.UserID);
        Map(x => x.Name);

    }
}

public class StudentMap: ClassMap<Student>
{
    public StudentMap()
    {
        Table("Student");
        Id(x => x.UserID);
        Map(x => x.Firstname);
        Map(x => x.Lastname);    
    }
}

回答1:

There are few really good articles on the internet about Fluent mapping and NHibernate inheritance. One of them is about mapping-by-code, but it provides detailed explanation about the Fluent mapping as well (just scroll down)

Mapping-by-Code - inheritance by Adam Bar

small extract related to your scenario

... Table per class

The second strategy for mapping inheritance is table per class with joined subclasses. In this option subclasses are stored in separate tables that have foreign key to base class table and are joined with the table for base class, if needed. In this case, in mapping-by-code, we have to map subclasses by inheriting from JoinedSubclassMapping. Here is the example of joined subclass mapping with all available options:

public class CompanyMap : JoinedSubclassMapping<Company>
{
    public CompanyMap()
    {
        Key(k =>
        {
            k.Column("PartyId");
            // or...
            k.Column(c =>
            {
                c.Name("PartyId");
                // etc.
            });

            k.ForeignKey("party_fk");
            k.NotNullable(true);
            k.OnDelete(OnDeleteAction.Cascade); // or OnDeleteAction.NoAction
            k.PropertyRef(x => x.CompanyName);
            k.Unique(true);
            k.Update(true);
        });

        Property(x => x.CompanyName);
    }
}

Another really good and comprehensive article:

Inheritance mapping strategies in Fluent Nhibernate by Igor Ignatov


BUT, I would suggest:

Do not go this way. Do NOT use inheritance if possible. If you have to - do not use so deep inheritance.

Please, do read this:

Composition over inheritance

small cite:

Benefits

To favor composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long term. In other words, HAS-A can be better than an IS-A relationship.

Initial design is simplified by identifying system object behaviors in separate interfaces instead of creating a hierarchical relationship to distribute behaviors among business-domain classes via inheritance. This approach more easily accommodates future requirements changes that would otherwise require a complete restructuring of business-domain classes in the inheritance model. Additionally, it avoids problems often associated with relatively minor changes to an inheritance-based model that includes several generations of classes.

NHibernate is really tremendous tool, supporting almost any kind of our wish... but it still should not mean, that we should use it.