Database error ; the value of the foreign key is unknown

34 Views Asked by At

These are the models

public class theTask
{
    [Key]
    public int TaskId { get; set; }
    [MaxLength(50)]
    [DisplayName("Tasks")]
    public string Tasks { get; set; }
    public string TaskDescription { get; set; }
    [DisplayName("Task Status")]
    public bool TaskStatus { get; set; }

    public SubTask SubTask { get; set; }
}

and

public class SubTask
{
    [Key]
    public int SubTaskId { get; set; }
    [Required]
    [MaxLength(50)]
    [DisplayName("Sub Task")]
    public string SubTasks { get; set; }
    [MaxLength(100)]
    [DisplayName("Sub Task Description")]
    public string SubDescription { get; set; }
    [DisplayName("Status")]
    public bool SubStatus { get; set; }

    [Required]
    [ForeignKey("theTask")]
    public virtual theTask theTask { get; set; }

    public int TaskId { get; set; }
}

This is the modelBuilder

modelBuilder.Entity<SubTask>(entity =>
{
    entity.HasKey(st => st.SubTaskId);
    entity.Property(st => st.SubTasks);

    entity.HasOne(st => st.theTask)
          .WithOne(t => t.SubTask)
          .HasForeignKey<theTask>(t => t.TaskId)
          .IsRequired()
          .OnDelete(DeleteBehavior.NoAction);
});

and this is how I coded the insertion to the database

public IActionResult taskCreate(TasksViewModel taskVM)
{
    theTask theTask = new theTask();
    theTask.Tasks = taskVM.Tasks;
    theTask.TaskDescription = taskVM.TaskDescription;
    theTask.TaskStatus = false;

    SubTask subTask = new SubTask();
    subTask.SubTasks = taskVM.SubTasks;
    subTask.SubDescription = taskVM.SubDescription;
    subTask.SubStatus = false;

    _db.Tasks.Add(theTask);
    _db.SubTasks.Add(subTask);
    _db.SaveChanges();

    return View();
}

I can't seem to understand why the foreign key is null or unknown. Without the foreign key the program seems to run just fine and my TaskId works normally but when I add the foreign key it always gets an error. I think I've encountered every error pertaining to the Foreign Key at this point lol.

System.InvalidOperationException: 'The property list specified using [ForeignKey("theTask")] attribute on navigation 'SubTask.theTask' is incorrect. Provide a comma-separated list of property names.'

And when I remove the [ForeignKey("task & subtask")], I get:

System.InvalidOperationException: 'The value of 'theTask.TaskId' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known.'

Edit: I am using EntityFramework 8.0.3 and sqlserver 8.0.3 (sorry I'm kinda new to this) and I'm just using the local sql server management 19. I know I can most probably do this in sql but I'm stubbornly trying to learn the 'code first' approach.

I am genuinely confused.

Thanks in advance

1

There are 1 best solutions below

0
marc_s On

Assuming you're using Entity Framework - possibly with a SQL Server backend - this approach might work (unfortunately, you haven't really specified the relevant environment info in your question...)

You're creating both your Task and your SubTask separately - without any connection between the two.

If you want to establish a foreign key relationship between them, you need to set the foreign key value for Task (or the TaskId) in your SubTask object, before saving.

If that TaskId is an identity column in SQL Server, then of course you cannot get the Id value before actually saving the data - but you CAN establish the link between the two objects, and let Entity Framework handle setting the proper TaskId value when saving the sub task.

Like this:

public IActionResult taskCreate(TasksViewModel taskVM)
{
    theTask theTask = new theTask();
    theTask.Tasks = taskVM.Tasks;
    theTask.TaskDescription = taskVM.TaskDescription;
    theTask.TaskStatus = false;

    SubTask subTask = new SubTask();
    subTask.SubTasks = taskVM.SubTasks;
    subTask.SubDescription = taskVM.SubDescription;
    subTask.SubStatus = false;
    // *NEW* - setting "theTask" on the subtask to establish link
    subTask.theTask = theTask;

    _db.Tasks.Add(theTask);
    // not really necessary - saving "theTask" will also save "subTask"
    // _db.SubTasks.Add(subTask);
    _db.SaveChanges();

    return View();
}