ASP.NET Core 6 EF一对多关联中Subject列表ClassName为空问题
ASP.NET Core 6 EF中Subject列表页面ClassName列显示为空的问题
我正在开发一个基于ASP.NET Core 6 Entity Framework的项目,包含多个数据表。已创建模型并生成数据库,但创建CRUD操作表单后,Subject的Index页面中ClassName列显示为空,Classe的添加功能正常。
模型代码
public class Subject { public int Id { get; set; } public string SubjectName { get; set; } [NotMapped] public virtual Classe Classe { get; set; } } public class Classe { [Key] public int Id_class { get; set; } public string ClassName { get; set; } public ICollection<Subject> Subjects { get; set; } }
控制器代码
public class ClasseController : Controller { private readonly SchoolContext _context; public ClasseController(SchoolContext schoolContext) { _context=schoolContext; } public IActionResult Index() { var classe = _context.Classes.ToList(); return View(classe); } public IActionResult Create() { return View(); } [HttpPost] public IActionResult Create(Classe cls) { _context.Classes.Add(cls); _context.SaveChanges(); return RedirectToAction(nameof(Index)); } } public class SubjectController : Controller { private readonly SchoolContext _context; public SubjectController(SchoolContext context) { _context = context; } public async Task<IActionResult> Index() { return View(await _context.Subjects.ToListAsync()); } public IActionResult Create() { ViewBag.data = _context.Classes.ToList(); return View(); } [HttpPost] public IActionResult Create(Subject subject) { _context.Subjects.Add(subject); _context.SaveChangesAsync(); return RedirectToAction("Index"); } }
视图代码
Subject Index视图
@model IEnumerable<MySchool.Models.Subject> @{} <p> <a asp-action="Create">Create New</a> </p> <table class="table"> <thead> <tr> <th> @Html.DisplayNameFor(model => model.Id) </th> <th> @Html.DisplayNameFor(model => model.SubjectName) </th> <th> @Html.DisplayNameFor(model => model.Classe.ClassName) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Id) </td> <td> @Html.DisplayFor(modelItem => item.SubjectName) </td> <td> @Html.DisplayFor(modelItem => item.Classe.ClassName) </td> <td> <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> | <a asp-action="Details" asp-route-id="@item.Id">Details</a> | <a asp-action="Delete" asp-route-id="@item.Id">Delete</a> </td> </tr> } </tbody> </table>
Subject Create视图
@model MySchool.Models.Subject @{ ViewData["Title"] = "Create"; } <h1>Create</h1> <h4>Grade</h4> <hr /> <div class="row"> <div class="col-md-4"> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="SubjectName" class="control-label"></label> <input asp-for="SubjectName" class="form-control" /> </div> <div class="form-group"> <label >Classe</label> @Html.DropDownList("classId", new SelectList(ViewBag.data,"Id_class","ClassName"),"Select name" ) </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">Back to List</a> </div> @section Scripts { @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } }
Classe Index视图
@model IEnumerable<Classe> @{} <a asp-action="Create">Ajouter</a> <table class="table"> <thead> <tr> <th>Id</th> <th>Classe name</th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td>@item.Id_class</td> <td>@item.ClassName</td> </tr> } </tbody> </table>
Classe Create视图
@model Classe @{} <a asp-action="Index">Liste</a> <form method="post"> <label asp-for="ClassName">Nom du classe</label> <input asp-for="ClassName"/> <input type="submit" value="Ajouter"/> </form>
DbContext代码
public SchoolContext(DbContextOptions<SchoolContext> options):base(options) { } public DbSet<Classe> Classes { get; set; } public DbSet<Subject> Subjects { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Classe>() .HasMany(b => b.Subjects) .WithOne(); }
我可以正常添加Classe,但添加Subject后,Subject列表页面的ClassName列显示为空,请问这是什么原因?
问题原因及解决办法
核心问题点
- Subject模型中Classe属性被标记为[NotMapped]:该特性会让EF忽略此属性,不会在数据库生成外键字段,导致Subject与Classe的关联无法持久化,查询时无法加载关联数据。
- 创建Subject时未接收并保存关联的Classe ID:视图下拉框name为
classId,但Subject模型无对应属性,提交后无法保存选中的班级ID。 - 查询Subject时未加载关联的Classe数据:当前查询仅获取Subject列表,未用Include方法加载关联实体,即使数据库有外键也无法自动获取关联数据。
具体修复步骤
1. 修改Subject模型
移除[NotMapped]特性,添加外键属性:
public class Subject { public int Id { get; set; } public string SubjectName { get; set; } // 外键属性,对应Classe的主键Id_class public int ClasseId { get; set; } // 导航属性 public virtual Classe Classe { get; set; } }
2. 更新DbContext关联配置
明确关联关系与外键:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Classe>() .HasMany(b => b.Subjects) .WithOne(s => s.Classe) .HasForeignKey(s => s.ClasseId); }
执行数据库迁移更新表结构:
Add-Migration AddSubjectClasseForeignKey Update-Database
3. 修改Subject Create视图下拉框
让下拉框name匹配模型的外键属性ClasseId:
<!-- 替换原DropDownList代码 --> <select asp-for="ClasseId" asp-items="@(new SelectList(ViewBag.data, "Id_class", "ClassName"))" class="form-control"> <option value="">Select name</option> </select>
4. 修正Subject控制器Create方法
确保异步操作等待,添加模型验证:
[HttpPost] public async Task<IActionResult> Create(Subject subject) { if (ModelState.IsValid) { _context.Subjects.Add(subject); await _context.SaveChangesAsync(); return RedirectToAction("Index"); } ViewBag.data = _context.Classes.ToList(); return View(subject); }
5. 修改Subject控制器Index方法,加载关联数据
使用Include方法加载关联的Classe实体:
public async Task<IActionResult> Index() { var subjects = await _context.Subjects .Include(s => s.Classe) .ToListAsync(); return View(subjects); }
完成以上修改后,添加Subject时会正确保存班级ID,列表页面即可正常显示班级名称。
内容的提问来源于stack exchange,提问作者user95
相关产品推荐
相关产品推荐

