Entity Framework model class has conditional one-to-one relationship

asp.net-mvc c# entity-framework-6 foreign-key-relationship

Question

I need some help here. I am having major problems creating my models based off of my ideas for my project. To simplify things, I have a Parent table, a Student table, and an Address table. So, each Parent record, can have multiple Students and only a single address. Each Student record, can have multiple Parents and only a single address. Logically, I really can't assume that the students address is the same as the parents address, since there can be a student with parents living in different locations. So, I would like to be able to have an address for student as well as an address for each parent. So, I basically envision this DB layout to come down to an Address table, with AddressID, street, city, state, zip.. And then a student table, with StudentID, name, addressID. And then a Parent table with ParentID, name, addressID. And then a Parent_Student reference table, with StudentID and ParentID.

So, any thoughts on how I can implement this? I created my Address Model with just the address information and ID. I created my Student model with ID, name, Virtual Address, and Virtual ICollection Parent. And then created my Parent model with ID, name, Virtual Address, and Virtual ICollection. When I try to create my Student controller via New->Scaffolded Item, I get an error about VS unable to determine the principal end of an association between the types Parent and Address.

I'm assuming this has to do with the fact that an address record willhave a foreign Key to either Parent or Student, but not both. I'm pretty new to this whole code-first approach, so any insight would be greatly appreciated. Thanks in advance!


EDIT: Adding UPDATED Code

PERSON Model:

public enum PersonType
{
    Student, Parent, Teacher
}

public abstract class Person
{

    [Key]
    public int PersonId { get; set; }

    [Required]
    [StringLength(50,ErrorMessage = "First Name cannot be longer than 50 characters.")]
    [Display(Name= "First Name")]
    public string FirstName { get; set; }

    [StringLength(50, ErrorMessage = "Middle Name cannot be longer than 50 characters.")]
    [Display(Name = "Middle Name")]
    public string MiddleName { get; set; }

    [Required]
    [StringLength(50, ErrorMessage = "Last Name cannot be longer than 50 characters.")]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
    public PersonType personType {get; set;}

    public Address Address { get; set; }

    [Display(Name = "Full Name")]
    public string FullName
    { 
        get
        {
            return FirstName + " " + LastName;
        }
    }

    [Display(Name = "Full Name w Middle")]
    public string FullNameWMid
    { 
        get
        { 
            return FirstName + " " + MiddleName + " " + LastName;
        }
    }
}

Student Model:

public class Student : Person
{
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:mm-dd-yyyy}", ApplyFormatInEditMode = true)]
    [Display(Name = "Birthday")]
    public DateTime Birthday { get; set; }
    public ICollection<int> ParentList { get; set; }

    public virtual ICollection<Parent> Parents { get; set; }
    public virtual Teacher Teacher { get; set; }


}

Parent Model:

public class Parent : Person
{       
    public string EmailAddress { get; set; }
    public ICollection<int> StudentList { get; set;  }

    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
    public virtual ICollection<Student> Students { get; set; }

}

Address Model:

public class Address
{
    public int AddressId { get; set; }
    public string StreetLine1 { get; set; }
    public string StreetLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }

    public Person Person { get; set; }

}
1
0
8/12/2014 12:18:08 AM

Popular Answer

Yeah, you're going to have a number of problems here. First, Entity Framework only supports 1:1 relationships when they use a "shared primary key". That means the Address ID and the Parent or Student ID have to be the same, and the address has to be a foreign key to the other.

I know it seems easy to just create navigation properties to each and you should have a 1:1, but you have to consider how this gets created in the database. What it actually creates is two separate 1:many relationships. And, since there is nothing to prevent you from assigning more than one entity to the many end, this results in a situation EF doesn't support.

This of course makes things difficult since you have several tables to link the address to.

I would suggest instead creating a "Person" entity which both Student and Parent derive from, then use TPH or TPC inheritance to create your Student and Parent unique entities.

This allows your Parents and Students to share a common ID, which you can then use as your 1:1 shared key with your address entity.

You can find out more here:

http://blog.bennymichielsen.be/2011/06/02/entity-framework-4-1-one-to-one-mapping/

1
8/11/2014 4:59:47 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow