none
Inheritance Issue with EF5 RRS feed

  • Question

  • I'm dealing with a legacy database. I have a Check table. This table includes all the normal data like CheckDate, CheckNo, and CheckAmount. It also has RecipientId and RecipientTypeId. The recipient of the Check can either be a person or a company.

    If RecipientTypeId is 1, we are to look for the RecipientId in the Persons table. Here RecipientId is PersonId. If the RecipientId is 2, we are suppose to look in the Company table, where RecipientId is asscociated with CompanyId.

    I was thinking of created classes like:

    public class Check
    {   public int CheckId
        {
            get;
            set;
        }
    
        public string CheckNo
        {
            get;
            set;
        }
    
        public DateTime CheckDate
        {
            get;
            set;
        }
    
        public decimal CheckAmt
        {
            get;
            set;
        }
    
        public int RecipientId
        {
            get;
            set;
        }
    
        public CheckRecipient Recipient
        {
            get;
            set;
        }
    }
    
    public abstract class CheckRecipient
    {   public int RecipientId
        {
            get;
            set;
        }
    
        public string Name
        {
            get;
            set;
        }
    }
    
    public class CheckRecipientCompany : CheckRecipient
    {
        public int CompanyId
        {
            get;
            set;
        }
    
        public string CompanyName
        {
            get;
            set;
        }
    }
    
    public class CheckRecipientPerson : CheckRecipient
    {
        public int PersonId
        {
            get;
            set;
        }
    
        public string LastName
        {
            get;
            set;
        }
    }

    How do I model this in EF 5.0. Since the discriminating Column is in the Check class, I can't use the following code in the EntityTypeConfiguation:    Map( m => m.Requires("RecipientTypeId").HasValue(1) );

    The problem with this is that EF thinks the RecipientTypeId column is in the Persons table instead of the Check table, so it errors out.

    Wednesday, August 7, 2013 5:32 AM

Answers

  • I'm familiar with Table-per-Hierarchy. I was trying for a smoother, more elegant model than what I had to come up with.

    Even though RecipientCompany and RecipientPerson are mutually exclusive according to the "RecipientTypeId", EF goes to the database and populates each one, even with the conditional mapping.

    So I came up with a model that works, but has exposed properties that should only be used for infrastructure and takes a performance hit by query extra tables.

    I read some hopeful news about EF6 that could help with these problems later

    Wednesday, August 14, 2013 6:32 PM

All replies

  • Hello Chris,

    Welcome to MSDN Forum.

    According to your description of the problem, the issue you are experiencing is the usage of  Mapping the Table-Per-Hierarchy(TPH) Inheritance.

    I’d like to refer you to  our MSDN reference below:

    How to use Table-Per-hierarchy .

    I would suggest you to try this coding below in your project.

    modelBuilder.Entity<CheckRecipient>().
    Map<CheckRecipientCompany>(m => m.Requires("RecipientTypeId").HasValue("1")).
    Map<CheckRecipientPerson>(m => m.Requires("RecipientTypeId").HasValue("2"));

    When I reproduce this issue, I find that there was an exception about “EntityType ‘CheckRecipient’ has no key defined. Define the key for this EntityType”. This issue was caused by EntityType has no primary key.

    The Entity Framework convention for primary keys is:
    1.Your class defines a property whose name is “ID” or “Id”
    2.or a class name followed by “ID” or “Id”

    So I suggest you to modify your CheckRecipient Class.

    public abstract class CheckRecipient
    {
        public int CheckRecipientId
        {
            get;
            set;
        }
        //public string Name
        //{
        //    get;
        //    set;
        //}
    }

    I hope this will help resolve your problem. If anything is unclear, please free feel to let us know.

    Best Regards,





    Thursday, August 8, 2013 1:43 AM
    Moderator
  • I'm familiar with Table-per-Hierarchy. I was trying for a smoother, more elegant model than what I had to come up with.

    Even though RecipientCompany and RecipientPerson are mutually exclusive according to the "RecipientTypeId", EF goes to the database and populates each one, even with the conditional mapping.

    So I came up with a model that works, but has exposed properties that should only be used for infrastructure and takes a performance hit by query extra tables.

    I read some hopeful news about EF6 that could help with these problems later

    Wednesday, August 14, 2013 6:32 PM
  • I'm familiar with Table-per-Hierarchy. I was trying for a smoother, more elegant model than what I had to come up with.

    Even though RecipientCompany and RecipientPerson are mutually exclusive according to the "RecipientTypeId", EF goes to the database and populates each one, even with the conditional mapping.

    So I came up with a model that works, but has exposed properties that should only be used for infrastructure and takes a performance hit by query extra tables.

    I read some hopeful news about EF6 that could help with these problems later

    Hi Chris,

    Thank you for sharing your experience here. It will be very beneficial for other community members who have  similar questions.

    Best Regards,


    Thursday, August 15, 2013 5:10 AM
    Moderator