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

ASP.NET创建Poll时重复添加记录及外键错误问题咨询

投票创建功能异常问题解决

问题现象

创建投票(Poll)及对应选项(PollOption)时,提交表单后数据库出现以下异常:

  • 新增3条Poll记录,其中1条包含正确的问题内容,另外2条为空
  • PollOption虽成功添加,但外键PollId指向了空Poll记录的ID
  • 移除选项添加功能后,Action可正常添加1条正确Poll记录,但无法同时创建PollOption

核心原因

  1. PollOption模型默认初始化导致额外Poll实例:在PollOption类中,导航属性Poll被默认初始化为new Poll(),EF Core会将每个PollOption附带的空Poll实例都当作新记录插入数据库,这就是额外空Poll的来源。
  2. 未手动关联正确的Poll外键:提交的PollOption未设置正确的PollId,EF只能将其关联到自动创建的空Poll实例。

修正方案

1. 修正PollOption模型

移除导航属性的默认初始化,避免自动创建空Poll实例:

public class PollOption
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Option { get; set; } = "";

    [Required]
    public int PollId { get; set; }

    [ForeignKey("PollId")]
    [ValidateNever]
    public Poll? Poll { get; set; } // 去掉默认new Poll()
}

2. 完善Poll模型(可选但推荐)

添加Poll与PollOption的导航集合,让EF更清晰处理关联关系:

public class Poll
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Question { get; set; } = "";

    // 添加导航集合,关联对应的选项
    public ICollection<PollOption> PollOptions { get; set; } = new List<PollOption>();
}

3. 修正Create Action

先保存Poll获取ID,再为每个PollOption设置正确的PollId后保存:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(PollVM pollVM) 
{
    // 1. 保存主Poll记录,获取自动生成的ID
    _unitOfWork.Poll.Add(pollVM.Poll);
    _unitOfWork.Save(); 

    // 2. 为每个选项绑定正确的Poll外键
    foreach (var option in pollVM.PollOptions)
    {
        option.PollId = pollVM.Poll.Id;
        _unitOfWork.PollOption.Add(option);
    }

    _unitOfWork.Save();

    return RedirectToAction(nameof(Index)); // 重定向避免重复提交
}

如果使用导航集合,Action可简化为:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(PollVM pollVM) 
{
    // 将选项关联到Poll的导航集合,EF自动处理外键
    pollVM.Poll.PollOptions = pollVM.PollOptions.ToList();
    _unitOfWork.Poll.Add(pollVM.Poll);
    _unitOfWork.Save();

    return RedirectToAction(nameof(Index));
}

4. 视图优化(可选)

新增选项时不需要提交Id(数据库自动生成),可移除隐藏的ID输入:

<div class="form-option">
    <!-- 移除冗余的ID隐藏输入 -->
    <input name="PollOptions[0].Option" type="text" placeholder="Option 1" required>
    <img src="~/images/icons/cross.svg" alt="remove-option" width="30px" class="remove-option" onclick="removeOption(this)">
</div>

内容的提问来源于stack exchange,提问作者Khaled Al Hariri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:29:52