user4287347
user4287347

Reputation:

Issue with many to many relationship using code first mvc

I created two models of Class and Teacher, I want to configure many to many relationship using code first approach with two models. When I add information into class and teacher tables, value not insert into TeacherClasses Table using many to many relationship Entity Framework code first approach.

Here code of models and controller below.

This is Class Model

public class Class
{
    [Key]
    public int ClassId { get; set; }

    [Required]
    public string ClassName { get; set; }

    public virtual ICollection<Teacher> Teachers { get; set; }

}

This is Teacher Model

public class Teacher
{
 [Key]  
    public int TeacherId { get; set; }

    [Required]
    public string TeacherName { get; set; }

    [DataType(DataType.Date)]
    public DateTime JoiningDate { get; set; }
    public decimal Salary { get; set; }
    public string Email { get; set; }


    public virtual ICollection<Class> Classes { get; set; }


    [NotMapped]
    public virtual Class Class { get; set; }
    [NotMapped]
    public virtual ICollection<int> SelectedClassList { get; set; }

}

This is Teacher Controller

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "TeacherId,TeacherName,JoiningDate,Salary,Email,Classes,Class,SelectedClassList")] Teacher teacher)
    {
        if (ModelState.IsValid)
        {
            db.Teachers.Add(teacher);
            db.SaveChanges();

            teacher.Classes = new Collection<Class>();

            foreach (var classId in teacher.SelectedClassList)
            {
                teacher.Classes.Add(new Class {ClassId = classId });
            }

            return RedirectToAction("Index");
        }
        return View(teacher);
    }

this is image of database tables in database class, teacher and teacherclasses tables shown

database

This is View of Teacher

<div class="form-group">
    @Html.Label("Class List", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @*@Html.ListBox("SelectedClassList", ViewData["ClassList"] as MultiSelectList)
        @Html.ValidationMessageFor(model => model.Classes, "", new { @class = "text-danger" })*@
        @Html.ListBoxFor(model => model.SelectedClassList, new MultiSelectList(ViewBag.ClassList, "value", "text"), new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.SelectedClassList, "", new { @class = "text-danger" })

    </div>
</div>

Upvotes: 0

Views: 199

Answers (1)

Gert Arnold
Gert Arnold

Reputation: 109117

From your description and the way you're saving the data there seem to be two possible scenarios you're trying to achieve:

  1. Insert new teachers and connect them to existing classes.
  2. Connect existing teachers to existing classes.

Whichever it is, the rule is always:

  • First attach existing entities to the context
  • Then add new entities

So for the first scenario that would be:

foreach (var classId in teacher.SelectedClassList)
{
    var class = new Class { ClassId = classId }; // "stub" entity
    db.Classes.Attach(class);
    teacher.Classes.Add(class); // Assuming that teacher.Classes isn't null
}
db.Teachers.Add(teacher); // <= Add
db.SaveChanges();

And the second scenario:

db.Teachers.Attach(teacher); // <= Attach
foreach (var classId in teacher.SelectedClassList)
{
    var class = new Class { ClassId = classId }; // "stub" entity
    db.Classes.Attach(class);
    teacher.Classes.Add(class); // Assuming that teacher.Classes isn't null
}
db.SaveChanges();

As you see, you never need to pull existing entities from the database. For creating associations all EF needs tho know is the ID values of the entities at both ends, so working with stub entities is the ideal approach here.

In the first scenario, if you don't attach the classes before adding the teacher, the classes will be marked as Added too, and you'll insert empty class records into the database (if they pass validation at all).

Upvotes: 1

Related Questions