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.
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
and CONF_Contract_Status
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