Home > Back-end >  Explicit loading in EF Core randomly loads .Include()
Explicit loading in EF Core randomly loads .Include()

Time:10-17

I have .NET 5 project with Index page where is table containing all rows from table Contracts, each row has Contract_StatusID column where is saved FK from table Contract_Statuses - table Contracts has more columns with this logic

Thing is, that Explicit loading is loading fully only last row of the table, other row's columns are randomly null, even when collection is .Include(s => s.Contract_Status) from controller code. All ID columns are set, and these IDs are existing in related tables, but not loaded into this table on Index page.

Detail page always correctly load all .Include() relation tables but not on Index page.

I've validated my models and they looks OK, and work within other pages of the site.

What I am missing? Already went through MSDN and EFCore tutorials for this, but it just don't work.

enter image description here

public async Task<IActionResult> Index()
{
    var contract = await context.Contracts
        .Include(c => c.Employee)
            .ThenInclude(c => c.Gender)
        .Include(i => i.Business_Unit)
        .Include(i => i.Brand)
        .Include(i => i.Contract_Status)
        .Include(i => i.Statutory_Unit)
        .Include(i => i.Management_Market).ToListAsync();
    return View(contract);
}

Edit: Adding my Index.cshtml

@model IEnumerable<MyProject.Models.Contract>    
<table >
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Employee)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Contract_Status.Contract_Status)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Business_Unit.Business_Unit)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Brand.Brand)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Statutory_Unit.Statutory_Unit)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Management_Market.Management_Market)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Employee.EmployeeID)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Contract_Status.Contract_Status)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Business_Unit.Business_Unit)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Brand.Brand)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Statutory_Unit.Statutory_Unit)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Management_Market.Management_Market)
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@item.ContractID">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.ContractID">Details</a>
                </td>
            </tr>
            }
        </tbody>
    </table>

And my Contract model with example of related table

    public class Contract
    {
        [Key]
        [Required]
        public Guid ContractID { get; set; }

        [Required]
        public string EmployeeID { get; set; }
        public Employee Employee { get; set; }

        [Required]
        public int Contract_StatusID { get; set; }
        public CONF_Contract_Status Contract_Status { get; set; }

        [Required]
        public int Business_UnitID { get; set; }
        public CONF_Business_Unit Business_Unit { get; set; }

        [Required]
        public int BrandID { get; set; }
        public CONF_Brand Brand { get; set; }

        [Required]
        public int Statutory_UnitID { get; set; }
        public CONF_Statutory_Unit Statutory_Unit { get; set; }


        [Required]
        public int Management_MarketID { get; set; }
        public CONF_Management_Market Management_Market { get; set; }
    }

public class CONF_Contract_Status
{
    [Key]
    public int CS_ID { get; set; }

    [Required]
    [Display(Name = "Status")]
    public string Contract_Status { get; set; }

    [Required]
    public bool Enabled { get; set; }

    public Contract Contract { get; set; }
}

DB screenshot of Contract table enter image description here

and CONF_Contract_Status

enter image description here

CodePudding user response:

I usually alway create view model for index view, since it is usually needed several string columns, but it can have a lot of columsn. YOu don't need to bring from the server the whole record if you only need one column


 public class ContractVieModel
    {
        public Guid ContractID { get; set; }

        public string EmployeeName { get; set; }
        public  string Contract_Status { get; set; }
        public string Business_Unit { get; set; }
        
      .... and so on
    }

action, you don't to use Include explicetly

public async Task<IActionResult> Index()
{
    var model = await context.Contracts
    .Select(i=> new ContractViewModel
     {
       Id=i.Id,
       EmployeeName=i.Employee.Name
      Contract_Status =i.Contract_Status.Contract_Status,
      Business_Unit = i.Business_Unit.Business_Unit,
      ... and so on 
      }).ToListAsync();

    return View(model);
}

view

@model IEnumerable<ContractViewModel> 

......

try it , and if it is still not working then you will have to use left outer joins to get a view model

  • Related