如何在单个Razor Page(非MVC)中关联并展示两个模型的数据
解决一对多关联及Razor Page数据展示问题
一、外键关联配置优化
你的模型已经基本符合EF Core一对多关系的要求,做两处优化可避免潜在问题:
- 显式标记外键:在Shot模型的导航属性上添加特性,明确关联的外键字段,让EF映射逻辑更清晰:
[Required] public int ChildId { get; set; } [ForeignKey(nameof(ChildId))] public Child Child { get; set; }
- 初始化集合避免空引用:在Child模型构造函数中初始化
Shots集合,防止后续访问时触发空引用异常:
public Child() { Shots = new List<Shot>(); }
二、修复Details页面后端逻辑
你的OnGet方法存在两处问题:查询结果未赋值给Child属性,且无需单独声明Shot属性(关联的Shot数据已包含在Child的Shots集合中)。修改后代码如下:
using HealthyShots.Data; using HealthyShots.Models; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; namespace HealthyShots.Pages.Details { public class DetailsModel : PageModel { private readonly ApplicationDbContext _db; public Child Child { get; set; } public DetailsModel(ApplicationDbContext db) { _db = db; } public void OnGet(int Id) { Child = _db.Child .Include(child => child.Shots) .FirstOrDefault(child => child.ChildId == Id); } } }
三、修改Razor视图展示批量Shot数据
视图需遍历Child.Shots集合来展示所有免疫记录,同时修正若干细节错误:
@page @model HealthyShots.Pages.Details.DetailsModel @{ ViewData["Title"] = "Immunization Details"; } <h2>Details</h2> @if (Model.Child != null) { <div> <h4>Demographic Information</h4> <hr /> <table class="table table-bordeless" style="width:100%"> <tr> <td style="width: 10%"> <div class="mb-3"> <label asp-for="Child.ChildId"></label> <input asp-for="Child.ChildId" disabled class="form-control"/> </div> </td> <td style="width: 30%"> <div class="mb-3"> <label asp-for="Child.LastName"></label> <input asp-for="Child.LastName" disabled class="form-control"/> </div> </td> <td style="width: 30%"> <div class="mb-3"> <label asp-for="Child.FirstName"></label> <input asp-for="Child.FirstName" disabled class="form-control"/> </div> </td> <td style="width: 5%"> <div class="mb-3"> <label asp-for="Child.MiddleInitial"></label> <input asp-for="Child.MiddleInitial" disabled class="form-control"/> </div> </td> <td style="width: 25%"> <div class="mb-3"> <label asp-for="Child.BirthDate"></label> <input asp-for="Child.BirthDate" type="date" disabled class="form-control"/> </div> </td> </tr> </table> <table class="table table-bordeless" style="width:100%"> <tr> <td style="width: 25%"> <div class="mb-3"> <label asp-for="Child.Addr1"></label> <input asp-for="Child.Addr1" disabled class="form-control"/> </div> </td> <td style="width: 25%"> <div class="mb-3"> <label asp-for="Child.Addr2"></label> <input asp-for="Child.Addr2" disabled class="form-control"/> </div> </td> <td style="width: 25%"> <div class="mb-3"> <label asp-for="Child.City"></label> <input asp-for="Child.City" disabled class="form-control"/> </div> </td> <td style="width: 5%"> <div class="mb-3"> <label asp-for="Child.State"></label> <input asp-for="Child.State" disabled class="form-control"/> </div> </td> <td style="width: 20%"> <div class="mb-3"> <label asp-for="Child.Zip"></label> <input asp-for="Child.Zip" disabled class="form-control"/> </div> </td> </tr> </table> <br /> <br /> <h4>Immunizations</h4> <hr /> @if (Model.Child.Shots.Any()) { <table class="table table-bordered" style="width:100%"> <thead> <tr> <th style="width: 20%">@Html.DisplayNameFor(m => m.Child.Shots.First().Date)</th> <th style="width: 20%">@Html.DisplayNameFor(m => m.Child.Shots.First().Dose)</th> <th style="width: 60%">@Html.DisplayNameFor(m => m.Child.Shots.First().ShotDesc)</th> </tr> </thead> <tbody> @foreach (var shot in Model.Child.Shots) { <tr> <td> <input asp-for="@shot.Date" type="date" disabled class="form-control"/> </td> <td> <input asp-for="@shot.Dose" disabled class="form-control"/> </td> <td> <input asp-for="@shot.ShotDesc" disabled class="form-control"/> </td> </tr> } </tbody> </table> } else { <p>No immunization records found.</p> } <a asp-page="/Children/Index">Back to List</a> </div> } else { <p>Child not found.</p> <a asp-page="/Children/Index">Back to List</a> }
主要修改点:
- 添加空值判断,避免空引用异常
- 遍历
Model.Child.Shots集合,展示所有免疫记录 - 修正FirstName输入框缺失的
disabled属性 - 移除多余的语法符号
- 添加空数据状态提示
内容的提问来源于stack exchange,提问作者MelB
相关产品推荐
相关产品推荐

