1

I'm trying to develop an application for school and I'm stuck. I want to add skills to a person using a Many-to-many relation in the database, so of course there's a table in between. I'm getting this error; Server Error in '/' Application.

Object reference not set to an instance of an object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.NullReferenceException: Object reference not set 

to an instance of an object.
Source Error: 

Line 99:                     var Skill = new Skill { ID = Skill_ID };
Line 100:                    var Teacher = new Teacher { ID = Teacher_ID };
**Line 101:                    Skill.Teachers.Add(Teacher);**
Line 102:                    db.SaveChanges();
Line 103:                }

This is my controller;

        // GET: MyProfile/AddkSkills/
        public ActionResult AddSkills()
        {
            var skills = (from s in db.Skills
                          select s); /*new Skill { ID = s.ID, SkillName = s.SkillName });*/

            var Model = new AddSkillsViewModel
            {
                Skills = skills.ToList(),
            };
            return View(Model);
        }

        //POST: MyProfile/AddkSkills/
        [HttpPost]
        public ActionResult AddSkillsPost()
        {
            int Teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
            var SkillsArray = Request.Form["chk_group[]"];
            if (SkillsArray != null)
            {
                foreach (var skill in SkillsArray)
                {
                    int Skill_ID = Convert.ToInt32(skill);

                    var Skill = new Skill { ID = Skill_ID };
                    var Teacher = new Teacher { ID = Teacher_ID };
                    Skill.Teachers.Add(Teacher);
                    db.SaveChanges();
                }
            }
            return RedirectToAction("MyProfile");
        }

Add Skill form;

<h2>AddSkills</h2>

<form name="addSkillsForm" action="AddSkillsPost" method="post">
    @foreach (var skill in Model.Skills)
    {
        <input type="checkbox" name="chk_group[]" value="@skill.ID" />@skill.SkillName< br />
    }
    <input type="submit" value="Update Skills" />
</form>

Edit1;

Skill Model

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace Ability_Examen_ASP.Models
{
    [Table("Skills")]
    public class Skill
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

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

        public virtual List<Teacher> Teachers { get; set; }
    }
}
Joren Polfliet
  • 101
  • 1
  • 8

2 Answers2

1

When you create a new Skill object, I assume that it's Teachers property is null. You may need to initialize that property to an empty list (or whatever).

A common technique is to have the default constructor for the Skill class (etc.) automatically create new collections for each such property.

For example (making assumptions about how your Skill and Teacher classes are defined):

public class Skill
{
    public Skill()
    {
        this.Teachers = new List<Teacher>();
    }
}

(Just add the inner part to your existing class).

This is something that would be done automatically if you were using EF Database-First, so I assume you're using Code-First.

Gary McGill
  • 26,400
  • 25
  • 118
  • 202
  • What would that look like in code? I'm really new to c# and wouldn't know where to start! Thank you for the answer. I added the skill model. – Joren Polfliet Jan 05 '16 at 15:32
  • Yeah, we had to use code first. I'll give it a shot, thanks. – Joren Polfliet Jan 05 '16 at 15:35
  • I added the line in the Skill model, but I still get the same error. – Joren Polfliet Jan 05 '16 at 15:37
  • When you say "the line", can I just confirm that you added all 4 lines of the constructor (i.e. from `public Skill()` down to the closing brace)? – Gary McGill Jan 05 '16 at 15:41
  • Oh apologies, I just added the inner line. The error is gone, but it's not adding anything to the database for some reason :(. – Joren Polfliet Jan 05 '16 at 15:46
  • where is your mapping logic? it's not adding to the database probably because you didn't map it properly – sowen Jan 05 '16 at 15:47
  • @JorenPolfliet If the original problem is solved, you might want to mark this question as answered and ask a new question. – Gary McGill Jan 05 '16 at 15:49
  • instead of creating a whole new question that's been asked a thousand times.. just make sure you add the skill to the context.. `db.Skill.Add(Skill);` right before `db.SaveChanges()` @JorenPolfliet – JamieD77 Jan 05 '16 at 15:51
  • @JorenPolfliet: JamieD77 is right - you're not adding any part of the object graph you've created to the context, so EF won't add it to the database. (Just pinging you explicitly in case you didn't see JamieD77's comment). – Gary McGill Jan 05 '16 at 15:55
  • Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. On db.SaveChanges(); now. Thanks for the help guys, appreciate it. If you prefer a new question for this one, I'll make one. – Joren Polfliet Jan 05 '16 at 16:03
  • @JorenPolfliet I think your problems now are quite far removed from where we started, so I think a new Q is appropriate. That said, you might be able to figure it out yourself if you examine the ValidationErrors property in the debugger. – Gary McGill Jan 05 '16 at 16:05
  • @JorenPolfliet validation is failing because you're not adding `SkillName` which is required for the `Skill` entity – JamieD77 Jan 05 '16 at 17:01
0

I think you'd be better off in this case just creating a junction table something like

[Table("TeacherSkills")]
public class TeacherSkill
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    [Required]
    public int TeacherID { get; set; }

    [ForeignKey("TeacherID ")]
    public Teacher Teacher { get; set; }

    [Required]
    public int SkillID{ get; set; }

    [ForeignKey("SkillID")]
    public Skill Skill { get; set; }
}

Then you just have to add your foreign keys to Teacher and Skill and to insert a new skill you simply

db.TeacherSkill.Add(new TeacherSkill(){TeacherID = Teacher_ID, SkillID = Skill_ID});
db.SaveChanges();
JamieD77
  • 13,796
  • 1
  • 17
  • 27