TheKingPinMirza
TheKingPinMirza

Reputation: 8922

How do i create One-to-One mapping in EF 6 using Data Annotation approach

I am using EF 6.1.1. I am unable to figure out how to create One-to-One relationship between two classes/tables with both entities have their owns PKs. I originally posted question link but could not get much help on it OR i am not able to get it. So, here i am putting my question in simple way.

Appreciate if someone can share thoughts on it.

My Requirement:

I would like create One-To-One relationship between Principle and Dependant with 'Id' from Principle class acts as Foreign Key in dependant class.

Principle Class

public class Student
{
    public string FullName {get; set;}
}

Dependant Class

public class StudentReport
{
    public string RollNumber { get; set; }
    public string StudentType { get; set; }
}

Upvotes: 0

Views: 152

Answers (1)

John Castleman
John Castleman

Reputation: 1561

Add PKs – EF requires this:

public class Student
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

public class StudentReport
{
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }
}

Note that EF 5 and later supports naming conventions: Id indicates a primary key. Alternately, it also supports the name of the class followed by "Id", so the above keys could have been StudentId for Student and StudentReportId for StudentReport, if you wished.

Add the foreign relation as a navigation property to at least one of the tables – in this case, you stated that StudentReport is the dependent, so let's add it to that one:

public class Student
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

public class StudentReport
{
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }

    public Student Student { get; set; }
}

Again – by naming convention – EF determines that a single Student property on StudentReport indicates that this is a navigational property associated with a foreign key. (By defining only the Student property, but no foreign key property, you are indicating that you don't care what EF names the associated FK ... basically, you're indicating you'll always access the related Student via the property.)

If you did care about the name of the FK property, you could add it:

public class Student
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

public class StudentReport
{
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }

    public int StudentId { get; set; }
    public Student Student { get; set; }
}

Again – by naming convention – EF determines that StudentId is the FK associated with the Student property because it has the class name, "Student", followed by "Id".

All of this, so far, has been using conventions as defined in Entity Framework Code First Conventions, but Data Annotations are also an option, if you wish:

public class Student
{
    [Key]
    public int Id { get; set; }
    public string FullName { get; set; }
}

public class StudentReport
{
    [Key]
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }

    [ForeignKey("Student")]
    public int StudentId { get; set; }
    public Student Student { get; set; }
}

Doing this is actually a good idea, because it makes clearer your intent to other programmers that might not be aware of EF Conventions – but can easily infer them from simply looking at EF Data Annotations – and is still less cumbersome than Fluent API.

UPDATE

I just realized, I left this as a one-to-many, with enforcement of the one-to-one relationship being left to do in the code using this model. To enforce the one-to-one in the model, you could add a navigation property to the Student class going the other way:

public class Student
{
    public int Id { get; set; }
    public string FullName { get; set; }

    public StudentReport StudentReport { get; set; }
}

public class StudentReport
{
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }

    public Student Student { get; set; }
}

However, that's going to break, because EF doesn't know which entity to insert first on an add. To indicate which is dependent, you have to specific that the dependent class' PK is the FK to the principal class (this enforces one-to-one because – in order for a Student/StudentReport pair to be associated – their Id properties must be the exact same value):

public class Student
{
    public int Id { get; set; }
    public string FullName { get; set; }

    public StudentReport StudentReport { get; set; }
}

public class StudentReport
{
    [ForeignKey("Student")]
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }

    public Student Student { get; set; }
}

or, using the full set of Data Annotations from earlier:

public class Student
{
    [Key]
    public int Id { get; set; }
    public string FullName { get; set; }

    public StudentReport StudentReport { get; set; }
}

public class StudentReport
{
    [Key, ForeignKey("Student")]
    public int Id { get; set; }
    public string RollNumber { get; set; }
    public string StudentType { get; set; }

    public Student Student { get; set; }
}

Upvotes: 1

Related Questions