You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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列显示为空,请问这是什么原因?


问题原因及解决办法

核心问题点

  1. Subject模型中Classe属性被标记为[NotMapped]:该特性会让EF忽略此属性,不会在数据库生成外键字段,导致Subject与Classe的关联无法持久化,查询时无法加载关联数据。
  2. 创建Subject时未接收并保存关联的Classe ID:视图下拉框name为classId,但Subject模型无对应属性,提交后无法保存选中的班级ID。
  3. 查询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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:12:15