简体   繁体   中英

Access a related table in EF Core

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

Post resolution update:

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

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM