1
votes

Getting the following error upon save of my context:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

The controller code:

#region CreateStory
[HttpPost]
[Authorize]
public ActionResult CreateStory(Userstory story)
{
    if (ModelState.IsValid)
    {
        string _Username = User.Identity.Name.ToLower();

        using (var _Db = new NimbleContext())
        {
            Project _Project = _Db.Projects.First(p => p.Owner.ToLower() == _Username);

            if (_Project != null)
            {
                ProjectGroup _Group = _Db.Groups.First(g => g.GroupID == story.GroupID);

                if (_Group != null)
                {                            
                    _Db.Userstories.Add(story);
                    _Db.SaveChanges(); <--- Error Occurs here!
                    return Json(new { Success = true, GroupID = _Group.GroupID });
                }
            }                                            
        }
    }
    return Json(new { Success = false });
}
#endregion

The Model structure:

Project 1 -> * Groups 1 -> * Userstories

I can prevent the error from occurring by removing the following declarations:

Project _Project = _Db.Projects.First(p => p.Owner.ToLower() == _Username);
ProjectGroup _Group = _Db.Groups.First(g => g.GroupID == story.GroupID);

However I need to make these checks to ensure that the user belongs to the project etc. I really don't see what is causing the error, none of those statements should have an impact on the data to be saved right?

1
I am creating some tests, and I don't think I want to implement the workaround suggested by the answer. What did you end up doing? - Arturo Hernandez

1 Answers

1
votes

Its all in your model design. If you are explicitly declaring your Foreign Key properties, do them like this:

public class Project {
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int ProjectId { get; set; }

   public virtual ICollection<Group> Groups { get; set; }
} 

public class Group {
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int GroupId { get; set; }

   [ForeignKey("Project"), DatabaseGenerated(DatabaseGeneratedOption.None)]
   public int? ProjectId { get; set; }

   public virtual Project Project { get; set; }
   public virtual ICollection<Userstory> Userstories{ get; set; }
} 

public class Userstory {
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int UserstoryId{ get; set; }

   [ForeignKey("Group"), DatabaseGenerated(DatabaseGeneratedOption.None)]
   public int? GroupId { get; set; }

   public virtual Group Group { get; set; }   
}

Note: This should work if you are following Entity Framework Code First, not sure about other methodologies like Model First and Database First