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

如何将问题字符串及对应选项列表同步添加至数据库?

解决方法:将问题与选项一同存入数据库

看起来你已经搞定了问题的存储,但卡在了关联选项这块。别担心,咱们一步步来解决这个问题,核心是利用EF Core的一对多关系和模型绑定来实现问题与选项的批量保存。

1. 先确认模型的关联关系

首先确保你的Question和Option模型已经正确配置了一对多关联,这是EF Core自动级联保存的基础:

Question.cs

public class Question
{
    public int Id { get; set; }
    [Required]
    public string Text { get; set; }
    // 其他问题相关属性(比如分类、难度等)
    // 导航属性:一个问题对应多个选项
    public ICollection<Option> Options { get; set; } = new List<Option>();
}

Option.cs

public class Option
{
    public int Id { get; set; }
    [Required]
    public string Text { get; set; }
    // 可选:标记是否为正确答案
    public bool IsCorrect { get; set; }
    // 外键:关联所属的问题
    public int QuestionId { get; set; }
    // 导航属性:选项属于一个问题
    public Question Question { get; set; }
}

别忘了在ApplicationDbContext中注册这两个实体:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

    public DbSet<Question> Questions { get; set; }
    public DbSet<Option> Options { get; set; }
}

2. 调整QuestionController的提交方法

你不需要单独保存选项,EF Core会自动级联保存关联的Options集合,只要你在保存Question时,它的Options已经被正确填充。修改你的AddQuestion POST方法:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddQuestion(Question question)
{
    if (ModelState.IsValid)
    {
        // 只需要添加Question,EF Core会自动添加关联的Options
        _context.Questions.Add(question);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index)); // 跳转到问题列表页
    }
    // 验证失败返回视图,保留用户输入
    return View(question);
}

3. 修改AddQuestion视图,实现选项的绑定

关键是让视图的输入框符合ASP.NET Core模型绑定的规则——集合类型的输入框name属性需要写成Options[N].PropertyName(N是索引,从0开始),这样模型绑定器才能把输入的选项填充到Question.Options集合中。

静态选项示例(固定数量)

如果你的问题选项数量固定(比如4个),可以直接用循环生成输入框:

@model Question

<h1>Add New Question</h1>

<form asp-action="AddQuestion">
    <!-- 问题文本输入 -->
    <div class="form-group mb-3">
        <label asp-for="Text" class="form-label">Question Text</label>
        <input asp-for="Text" class="form-control" />
        <span asp-validation-for="Text" class="text-danger"></span>
    </div>

    <!-- 选项区域 -->
    <h3 class="mb-2">Answer Options</h3>
    @for (int i = 0; i < 4; i++)
    {
        <div class="border p-3 mb-2">
            <div class="form-group">
                <label>Option @(i+1) Text</label>
                <input type="text" asp-for="Options[i].Text" class="form-control" />
                <span asp-validation-for="Options[i].Text" class="text-danger"></span>
            </div>
            <div class="form-check mt-2">
                <input class="form-check-input" asp-for="Options[i].IsCorrect" />
                <label class="form-check-label" asp-for="Options[i].IsCorrect">
                    Mark as correct answer
                </label>
            </div>
        </div>
    }

    <button type="submit" class="btn btn-primary">Save Question & Options</button>
</form>

动态添加选项(可选)

如果需要支持用户动态添加任意数量的选项,可以用JavaScript实现:

在视图底部添加这段JS:

<script>
    let currentOptionIndex = 4; // 初始有4个选项,从第5个开始计数

    // 添加按钮点击事件
    document.getElementById("add-option-btn").addEventListener("click", function() {
        // 克隆现有选项模板
        const optionTemplate = document.querySelector(".option-template").cloneNode(true);
        optionTemplate.classList.remove("d-none"); // 移除隐藏类

        // 更新输入框的name和id属性,符合模型绑定规则
        const textInput = optionTemplate.querySelector("[name^='Options']");
        textInput.name = `Options[${currentOptionIndex}].Text`;
        textInput.id = `Options_${currentOptionIndex}__Text`;

        const correctCheckbox = optionTemplate.querySelector("[type='checkbox']");
        correctCheckbox.name = `Options[${currentOptionIndex}].IsCorrect`;
        correctCheckbox.id = `Options_${currentOptionIndex}__IsCorrect`;

        // 清空输入值和复选框状态
        textInput.value = "";
        correctCheckbox.checked = false;

        // 添加到选项容器中
        document.getElementById("options-container").appendChild(optionTemplate);
        currentOptionIndex++;
    });
</script>

然后修改视图的选项区域:

<!-- 选项容器 -->
<div id="options-container">
    <!-- 初始4个选项 -->
    @for (int i = 0; i < 4; i++)
    {
        <div class="border p-3 mb-2">
            <div class="form-group">
                <label>Option @(i+1) Text</label>
                <input type="text" asp-for="Options[i].Text" class="form-control" />
                <span asp-validation-for="Options[i].Text" class="text-danger"></span>
            </div>
            <div class="form-check mt-2">
                <input class="form-check-input" asp-for="Options[i].IsCorrect" />
                <label class="form-check-label" asp-for="Options[i].IsCorrect">
                    Mark as correct answer
                </label>
            </div>
        </div>
    }

    <!-- 隐藏的选项模板,用于克隆 -->
    <div class="option-template border p-3 mb-2 d-none">
        <div class="form-group">
            <label>Option Text</label>
            <input type="text" name="Options[0].Text" class="form-control" />
        </div>
        <div class="form-check mt-2">
            <input class="form-check-input" type="checkbox" name="Options[0].IsCorrect" />
            <label class="form-check-label">
                Mark as correct answer
            </label>
        </div>
    </div>
</div>

<!-- 添加选项按钮 -->
<button type="button" id="add-option-btn" class="btn btn-secondary mb-3">Add Another Option</button>

4. 验证与测试

  • 确保Option的Text属性添加了[Required]特性,这样用户必须填写每个选项的内容。
  • 测试提交:填写问题和选项,点击提交后,查看数据库的Questions和Options表,确认问题和对应的选项都被正确保存,且Options表的QuestionId字段正确关联到问题的Id。

这样就能实现问题和选项的一键保存啦!

内容的提问来源于stack exchange,提问作者Guga Todua

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:47:15