13

I'm new to Entity Framework code-first. This is my learning in ASP.NET MVC, using code-first for database creation.

I have two classes:

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
    public int Standard { get; set; }            
    public int SubjectId { get; set; }    

    [ForeignKey("SubjectId")]
    public ICollection<Subject> Subjects { get; set; }
}

public class Subject
{
    [Key]
    public int SubjectId{ get; set; }
    public string SubjectName { get; set; }
}

I'm trying to insert a Student record into the Student table, which has a foreign key SubjectId referencing the Subject table.

I'm trying it out in two possible ways:

First approach

using(var cxt = new SchoolContext())
{
    Subject sub = new Subject() { SubjectId = 202, SubjectName ="Geology" };
    Student stu = new Student() { Name = "Riya", SubjectId = 202 };
    cxt.Subjects.Add(sub);
    cxt.Students.Add(stu);           

    cxt.SaveChanges();
}

Here I created a new Subject instance, which has SubjectId=202. Now when I create the Student object and assign value 202 to SubjectId, there is an Insert statement conflict. Though there is a Subject with SubjectId = 202, then why is there an insert conflict? And when I debug, I see that the navigation property Subjects is null here. I don't understand the point here.

Second approach:

using( var cxt=new SchoolContext())
{
    Student stu = new Student() { Name = "Riya" };
    Subject sub = new Subject() { SubjectId = 202, SubjectName = "Geology" };
    stu.Subjects.Add(sub);
    cxt.Students.Add(stu);               

    cxt.SaveChanges();
}

But I get an a null reference exception

Object Reference not set to instance of an Object

Why is the stu.Subjects null here?

So my questions here are:

  1. What does the SubjectId in Student class mean? I.e. what does its value pertain to? Can we explicitly set it, if yes, will it refer to primary key of Subject table? If no, is it specified only for EF code conventions purpose?

  2. Similarly: what does navigation property role? Why is it null and when it will not be null?

My basic understanding of navigation property is that it is used to make EF determine the relationship between the two entities.

Can anyone please clarify a bit with examples which would be greatly appreciated.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Raida Adn
  • 405
  • 1
  • 6
  • 17
  • 1
    There should be no SubjectId in your Student class. You are probably looking for [many-to-many](http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx): a student can have many subjects, a subject can have many students. – Steve Greene Aug 18 '17 at 14:39
  • In `Student`, make sure to mark your `Subjects` collection as virtual. – Tipx Aug 18 '17 at 14:40
  • @Tipx - Virtual is only needed if [lazy loading](https://stackoverflow.com/questions/15247614/understanding-code-first-virtual-properties) is desired. That's not the issue. – Steve Greene Aug 18 '17 at 14:45
  • First you need to decide what kind of relation you need, second you need to initialize the foreign key object to be able to insert via a foreign key – Lucian Bumb Aug 18 '17 at 14:52
  • See the student/courses example [here](http://www.entityframeworktutorial.net/entity-relationships.aspx) – Steve Greene Aug 18 '17 at 15:04
  • Can anyone specify me Which of my two approaches is correct? – Raida Adn Aug 18 '17 at 15:37
  • Neither of those approaches will work - see my answer – marc_s Aug 18 '17 at 16:00
  • @SteveGreene `StudentId` is used as primaryKey, Can you clarify me Why you say that `StudentId` makes no sense? – Raida Adn Aug 18 '17 at 18:28
  • Sorry, I meant the SubjectId inside the Student class and the [ForeignKey] attribute on the Subjects collection. See [here](http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx) for 1 to many or above for many to many. – Steve Greene Aug 18 '17 at 19:05
  • So Is it like if the entity is involved in a relationship having multiplicity greater than one, then no need to specify its primary key as foreign key in other enity. It's navigation property itself will do. – Raida Adn Aug 18 '17 at 19:21

1 Answers1

17

You're basically creating a new Student, and a new Subject, in both your approaches. But from what I understand, what you're really trying to do, is create a new Student, and assign an existing Subject (with SubjectId = 202) to it - right??

The SubjectId in your Student class makes absolutely no sense in this setup - since you have a 1:n relationship between Student and Subject. You need to use that ICollection<Subject> to handle the 0:n subjects this student is enrolled in.

For that - use this code:

using(var ctx = new SchoolContext())
{
    // create the *NEW* Student
    Student stu = new Student() { Name = "Riya" };

    // get existing subject with Id=202
    Subject sub = ctx.Subjects.FirstOrDefault(s => s.SubjectId == 202);

    // Add this existing subject to the new student's "Subjects" collection
    stu.Subjects.Add(sub);

    // Add the new student to the context, and save it all.
    ctx.Students.Add(stu);           

    ctx.SaveChanges();
}

That will do - a new student will be inserted into your database table, and the 1:n relationship between student and his subjects will be established.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Can't I do like this, Create a new `Subject`, call `SaveChanges`,next Create `Student` retreive Subject and add this `subject` to the new `Student` – Raida Adn Aug 18 '17 at 18:37