Fluent-NHibernate Multi-Level Inheritance based on

2019-08-18 02:02发布

问题:

I am having issues finding good documentation for the problem I am having. I am reconstructing a portion of an enterprise solution and swapping over the NHibernate for our ORM. I have 3 tables which I want to all inherit from each other.

MasterAccount : Account : InvBilling

**MasterAccount**
id_MasterAccount

**Account**
id_Account
id_MasterAccount
id_InvBilling

**InvBilling**
id_InvBilling
id_MasterAccount

For each row in MasterAccount there exists a row in Account where the Id_MasterAccount columns are equal and the IsMaster column is 1. However, there are also other records in the Account table which also have their id_MasterAccounts equal to associate with their parent account. Finally, every record in the Account table has a record in the InvBilling table.

I am having lots of issues setting up their mappings. Any help with how to set this up?

I need to somehow tell MasterAccount which Account record it should associate itself to as well as the column it should use.

Edit: Here is what I have so far:

public class MasterAccountEntity : AccountEntity{
    protected virtual int MAId {get;set;}
}

public class AccountEntity : InvBillingEntity{
    protected virtual int AId {get;set;}
    public virtual MasterAccountEntity MA {get;set;}
    public virtual InvBillingEntity IB {get;set;}
    public virtual bool IsMaster {get;set;}
}

public class InvBilling{
    protected virtual int IBId {get;set;}
    public MasterAccountEntity MA {get;set;}
}

Then for my mappings(somewhat lost on how to show the inheritance):

public class FluentHibernateMap : SubclassMap<MasterAccountEntity>{
    Table("MasterAccount");
    Map(x => x.MAId).Column("id_MasterAccount");
}

public class FluentHibernateMap : SubclassMap<AccountEntity>{
    Table("Account");
    Map(x => x.AId).Column("id_Account");
    Map(x => x.IsMaster).Column("isMaster");
    References(x => x.MA).Column("id_MasterAccount").Not.Nullable().Cascade.None();
    References(x => x.IB).Column("id_InvBilling").Not.Nullable().Cascade.None();
}

public class FluentHibernateMap : ClassMap<InvBillingEntity>{
    Table("InvBilling");
    Id(x => x.IBId).Column("id_InvBilling");
    References(x => x.MA).Column("id_MasterAccount").Not.Nullable().Cascade.None();
}

So MasterAccount needs to inherit the record from Account where IsMaster is true, and then inherit the record in InvBilling that cooresponds to the InvBillingId in Account.

回答1:

Account table is a Versioning table and it is effectivly the many side to the master table. i would reflect that and not try to hide this in the mapping. Then it would be impossible to do anything with the historic records and complexity rises without need.

public class Entity
{
    protected virtual int Id { get; private set; }  // should be readonly once set by NHibernate
}

public class AccountMasterEntry : Entity
{
    public virtual Account ActiveAccount { get; private set;}
}

public class Account : Entity
{
    public virtual AccountMasterEntry MA {get;set;}
    public virtual InvBillingEntity IB {get;set;}
    public virtual bool Active {get;set;}
}

public class InvBilling : Entity
{
}

public class AccountMasterEntryMap : ClassMap<AccountMasterEntry>
{
    public AccountMasterEntryMap()
    {
        Id(x => x.Id).GeneratedBy...;

        // optional
        References(x => x.ActiveAccount).Formula("(SELECT acc.id_Account FROM Account acc WHERE id_MasterAccount = acc.id_MasterAccount AND acc.IsMaster = 1)");
    }
}

public class AccountMap : ClassMap<Account>
{
    public AccountMap()
    {
        Id(x => x.Id).GeneratedBy...;

        References(x => x.MA, "id_MasterAccount");
        References(x => x.IB, "id_InvBilling");
        Map(x => x.Active, "ismaster");
    }
    public virtual AccountMasterEntry MA { get; set; }
    public virtual InvBilling IB {get;set;}
    public virtual bool IsMaster {get;set;}
}

public class InvBilling : Entity
{
}

// query
int masterId = ...;
var accountrecord = session.Query<Account>()
    .Where(a => a.MA.Id == masterId && a.Active)  // NHibernate should be smart enough to see that there is no join needed
    .Single();

Note: i'm not sure if invbillingId alone is unique or if it is a compositeid