Combine two classes from a table per hierarchy inheritance structure in Entity Framework

Viewed 39

We're are using the table per hierarchy inheritance technique with Entity Framework. I'll take the example classes from this page as the basic classes: Table per Hierarchy Inheritance - The Model. Please don't take the class names and properties as set. I didn't want to expose anything critical. This question is just about the structure.

public class Contract
{
    public int ContractId { get; set; }
    public DateTime StartDate { get; set; }
    public int Months { get; set;}
    public decimal Charge { get; set; }
}

public class MobileContract : Contract
{
    public string MobileNumber { get; set; }
}

public class TvContract : Contract
{
    public PackageType PackageType { get; set; }
}

public class BroadBandContract : Contract
{
    public int DownloadSpeed { get; set; }
}

public enum PackageType
{
    S, M, L, XL
}

Now, in our case we have the situation that there is a contract that can be both, a TvContract and a BroadBandContract, e.g. a MultiContract. We don't know how to deal with this since we cannot inherit from two classes. If we query the DbSet<TvContract> or DbSet<BroadBandContract> from the we also want to get the MultiContracts.

Does someone have an idea how to deal with this scenario?

1 Answers

I see our current class structure is of inheritance. While to me it looks like composition. A contract may contain different subcontracts and once the contract expires, subcontracts too expire. However, subcontracts are of different types and that is what you could use for your advantage. You may also see a requirement where someone would add or remove the packages they have thus contract type is not really static. I would design to handle that. I would have also preferred an end date or Months individually on SubContract allowing for variable start and end dates for SubContract obejcts.

I would redesign the classes like this and then only query Contract potentially with SubContract based filters.

public class Contract
{
    public int ContractId
    {
        get;
        set;
    }
    public DateTime StartDate
    {
        get;
        set;
    }
    public int Months
    {
        get;
        set;
    }
    public decimal Charge
    {
        get;
        set;
    }

    public bool IsMultiContract
    {
        get
        {
            return SubContracts.GroupBy(x => x.ContractType).Count() > 0;
        }
    }

    /// <summary>
    /// Optional unique check for subcontract types may be added
    /// </summary>
    public List<SubContract> SubContracts
    {
        get;
        set;
    }
}

public enum ContractType
{
    Broadband,
    Mobile,
    TV
}


public class SubContract
{
    public ContractType ContractType
    {
        get;
        set;
    }
}

public class MobileContract : SubContract
{
    public string MobileNumber
    {
        get;
        set;
    }
}

public class TvContract : SubContract
{
    public PackageType PackageType
    {
        get;
        set;
    }
}

public class BroadBandContract : SubContract
{
    public int DownloadSpeed
    {
        get;
        set;
    }
}

public enum PackageType
{
    S,
    M,
    L,
    XL
}
Related