Reputation: 131
I am trying to access a related table to display a column in my View.
I believe it is something quite fundamental I am not understanding but for the life of me can't solve it.
Simplified problem is, I have 3 Models Branch, Colleague, Staff Position. A Colleague currently is linked to 1 branch and can be only 1 Staff Positon.
Models are created using Code First
Branch
public class Branch
{
[Display(Name ="Branch ID")]
public int BranchNumber { get; set; }
[Display(Name ="Branch Name")]
public string BranchName { get; set; }
[Display(Name ="Contractor Code")]
public int ContractorCode { get; set; }
[Display(Name ="Addresss")]
public string AddressOne { get; set; }
... (Excluded for simplicity)...
public ICollection<BranchHour> BranchHours { get; set; }
public ICollection<Colleague> Colleagues { get; set; }
}
Colleague
public class Colleague
{
[Display(Name ="ID")]
public int ColleagueID { get; set; }
public int BranchID { get; set; }
public int StaffPositionID { get; set; }
[Display(Name ="Payroll Number")]
public string PayrollNumber { get; set; }
...(Excluded for simplicity)...
public ICollection<Shift> Shifts { get; set; }
[ForeignKey("StaffPositionID")]
public StaffPosition StaffPosition { get; set; }
[ForeignKey("BranchID")]
public Branch Branch { get; set; }
}
Staff Position
public class StaffPosition
{
public int StaffPositionID { get; set; }
public string PositionName { get; set; }
public ICollection<Colleague> Colleagues { get; set; }
}
I know that having the navigation properties in both classes is optional.
My View Model is
public class BranchShiftData
{
public IEnumerable<Branch> Branches { get; set; }
public IEnumerable<Colleague> Colleagues { get; set; }
public IEnumerable<Shift> Shifts { get; set; }
public IEnumerable<StaffPosition> StaffPos { get; set; }
}
Originally I didn't have Shifts and Staff Pos in there but I couldn't access Shifts data through Colleague I would expect without it.
This is the start of the OnGet for the Code Behind page
BranchData = new BranchShiftData();
BranchData.Branches = await _context.Branches
.Include(i => i.Colleagues)
.OrderBy(i => i.BranchNumber)
.ToListAsync();
if (id != null)
{
BranchID = id.Value;
Branch branch = BranchData.Branches
.Where(i => i.ContractorCode == id.Value).Single();
BranchData.Colleagues = branch.Colleagues
.OrderBy(i => i.FullName);
}
if (colleagueID != null)
{
ColleagueID = colleagueID.Value;
var selectedColleague = BranchData.Colleagues
.Where(x => x.ColleagueID == colleagueID).Single();
FullName = selectedColleague.FullName;
PayrollNumber = selectedColleague.PayrollNumber;
BranchName = selectedColleague.Branch.BranchName;
ContractHours = selectedColleague.ContractHours;
PositionName = selectedColleague.StaffPosition.PositionName;
So the issue I face is I am able to access the Branch Name by going through selectedColleague and its link to Branch, however, the same does not work for StaffPosition table and I can't understand why.
Once I select a single colleague in the web app it breaks at line starting PositionName due to the following error
NullReferenceException: Object reference not set to an instance of an object.
Which would be correct as the variables stack shows for the selectedColleague as StaffPosition null.
What I fail to understand is in the selectedColleague variable BranchID is 5558 (correct) and I have a object of Branch which when expanded is all the correct details for Branch 5558, however, selectedColleague's StaffPositionID is correct at 1 but yet StaffPosition is null.
The main question I have is why can I get the Branch name by going
BranchName = selectedColleague.Branch.BranchName
But can't access StaffPosition Name by going
PositionName = selectedColleague.StaffPosition.PositionName
For anyone who comes across this,Serge's answer below is spot on. If you want to read further on the ThenInclude function then check here
EF Core Docs
There is also another tutorial from MS hidden down in the docs list, this is for Razor pages but there is also one for MVC.
MS Tutorial
Upvotes: 2
Views: 968
Reputation: 43860
You have Branck in Branches already, but you have to add include for a StaffPosition. Try this
BranchData.Branches = await _context.Branches
.Include(i => i.Colleagues)
.ThenInclude(i => i.StaffPosition)
.OrderBy(i => i.BranchNumber)
.ToListAsync();
Upvotes: 3