简体   繁体   中英

How can i implement this design, with nhibernate.

I have a class say Expense, with beneficiaries, it can be Desk or User, so the Expense has one or more beneficiaries and it can be only one type, all Desk or all User with a different repartition.

[DataContract]
[KnownType(typeof(User))]
[KnownType(typeof(Desk))]
public abstract class Beneficiare
{
    [DataMember]
    public virtual  int Id { get; set; }
    [DataMember]
    public virtual string FullName { get; set; }
}

[DataContract]
public class Desk : Beneficiare
{
    [DataMember]
    public virtual int NbEmployee { get; set; }
    //other properties and method
}

[DataContract]
public class User : Beneficiare
{
    [DataMember]
    public virtual string Surname { get; set; }
    [DataMember]
    public virtual string LastName { get; set; }
    //other properties and method
}

[DataContract]
public class ExpenseRepartition
{
    [DataMember]
    public virtual int Id { get; set; }
    [DataMember]
    public virtual Beneficiare Beneficiare { get; set; }
    [DataMember]
    public virtual Expense Expense { get; set; }
    [DataMember]
    public virtual Decimal Percentage { get; set; }
}

[DataContract(IsReference = true)]
public class Expense
{
    [DataMember]
    public virtual int Id { get; set; }
    [DataMember]
    public virtual DateTime COBDate { get; set; }
    [DataMember]
    public virtual Amount Amount { get; set; }
    [DataMember]
    public virtual IList<ExpenseRepartition> Repartition  { get; set; }
}

So basically,with nhibernate, i can use for desk and user a " table per class hierarchy" or "table per concrete subclass". I don't like to use table per class hierrachy as they have a lot of different property so i'll end with a table in database with a lot of column and a lot of them null. I don't like to make inherite user and desk from the same object, appart having a name they are totally unrelated. Instead i was thinking to do something like that

[DataContract]
public class Desk
{
    [DataMember]
    public virtual  int Id { get; set; }
    [DataMember]
    public virtual string Name { get; set; }
    [DataMember]
    public virtual int NbEmployee { get; set; }
    //other properties and method
}

[DataContract]
public class User
{
    [DataMember]
    public virtual  int Id { get; set; }
    [DataMember]
    public virtual string FullName { get; set; }
    [DataMember]
    public virtual string Surname { get; set; }
    [DataMember]
    public virtual string LastName { get; set; }
    //other properties and method
}

[DataContract]
[KnownType(typeof(ExpenseRepartitionUser))]
[KnownType(typeof(ExpenseRepartitionDesk))]
public abstract class ExpenseRepartition
{
    [DataMember]
    public virtual int Id { get; set; }
    [DataMember]
    public virtual Expense Expense { get; set; }
    [DataMember]
    public abstract string BeneficiareName { get; }
    [DataMember]
    public virtual Decimal Percentage { get; set; }
}


[DataContract]
public class ExpenseRepartitionDesk :ExpenseRepartition
{
    [DataMember]
    public virtual Desk Beneficiare { get; set; }

    public override string BeneficiareName
    {
        get
        {
            return Beneficiare.Name;
        }
    }

}

[DataContract]
public class ExpenseRepartitionUser : ExpenseRepartition
{
    [DataMember]
    public virtual User Beneficiare { get; set; }
    public override string BeneficiareName
    {
        get
        {
            return Beneficiare.FullName;
        }
    }

}

[DataContract(IsReference = true)]
public class Expense
{
    [DataMember]
    public virtual int Id { get; set; }
    [DataMember]
    public virtual DateTime COBDate { get; set; }
    [DataMember]
    public virtual Amount Amount { get; set; }
    [DataMember]
    public virtual IList<ExpenseRepartition> Repartition  { get; set; }
}

Inheritance is on the expanserepartition class instead of desk and user, knowing that the percentage calculation can vary, for example if it's for a user it's up to the user to fill it if it's for a desk it depends on the number of the desk's employee/ total number of employee in the expense's repartition. So in this case with nhibernate a can use a table per hierarchy for expanse repartition with a discriminator-value in one column or a table per concrete class with just one column with the id of the user or desk. What is the best solution/design ? Or maybe there is another one.

From our discussion on the nhibernate mailing list

http://notherdev.blogspot.com/2012/01/mapping-by-code-inheritance.html

The third option is to use table per subclass with unioned subclasses. This time there is no separate table for base class, common columns are specified in each table for subclass separately and subclass tables share the same key generator. Mapping union subclasses with mapping-by-code is fairly simple - we just need to map the class by inheriting from UnionSubclassMapping - no additional requirements or options.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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