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

异步方法执行中断:数据库未成功添加问答数据求助

解决异步数据库操作中途停止、Answer无法添加的问题

可能的原因及解决方案

1. 捕获未处理的异步异常

异步方法抛出异常时如果没被捕获,很容易出现「静默失败」——看起来像是停止执行,实际是异常导致流程中断。给你的方法加上异常捕获:

在调用方CreateNewQuestion里包裹关键逻辑:

private async Task CreateNewQuestion()
{
    try
    {
        if (newQuestion.QuestionType is null)
        {
            noType = true;
            return;
        }
        else if (Answers.Count == 0)
        {
            noAnswer = true;
            return;
        }
        
        var questioncount = await questionRepo.GetQuestionByQuizId(QuizId);
        _order = questioncount.Count + 1;
        newQuestion.QuestionOrderId = _order;
        newQuestion.AnswerType = _answerType;
        newQuestion.QuestionUrl = _questionUrlConverted;
        
        await questionRepo.AddQuestionWithAnswers(newQuestion, Answers);
        
        noType = false;
        questions = await questionRepo.GetQuestionByQuizId(QuizId);
        var quiz = quizRepo.GetQuizById(QuizId);

        Navigation.NavigateTo($"/Quiz/AddQuestionWithId/{QuizId}", true);
    }
    catch (Exception ex)
    {
        // 输出异常日志,或在UI上展示错误提示
        Console.WriteLine($"操作失败:{ex.Message}\n{ex.StackTrace}");
        // 示例:设置错误提示变量供UI渲染
        errorMessage = $"添加问题失败:{ex.Message}";
    }
}

同时在AddQuestionWithAnswers内部也加上捕获:

public async Task AddQuestionWithAnswers(Question newQuestion, List<Answer> answers)
{
    if(newQuestion is null || answers.Count == 0) return;
    
    try
    {
        _context.Questions.Add(newQuestion);
        await _context.SaveChangesAsync();

        // SaveChanges后newQuestion的QuestionId已自动赋值,无需再查询数据库
        foreach(var answer in answers)
        {
            answer.QuestionId = newQuestion.QuestionId; // 直接设置外键更可靠
            _context.Answers.Add(answer);
        }
        // 批量保存所有Answer,减少数据库交互次数
        await _context.SaveChangesAsync();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"保存数据失败:{ex.Message}");
        throw; // 将异常抛回调用方统一处理
    }
}

2. 检查DbContext的生命周期

如果你的DbContext是单例模式,或者被多个线程共享,异步操作极易出现死锁或阻塞。确保在ASP.NET Core中使用Scoped生命周期的DbContext(默认配置即为Scoped),每个请求/操作使用独立实例,避免并发冲突。

3. 优化实体操作逻辑

  • 移除多余的GetQuestionById调用:EF Core在执行SaveChangesAsync后,会自动把生成的主键赋值给newQuestion.QuestionId,直接用这个值关联Answer即可,无需重复查询数据库。
  • 批量保存Answer:不要在循环中每次添加都调用SaveChangesAsync,先将所有Answer加入上下文,最后一次性保存,既提升效率,也降低出错概率。

4. 检查实体关系配置

确认Question和Answer的实体映射是否正确:

  • Answer类是否包含QuestionId外键属性,且与Question的主键正确关联。
  • 检查EF Core的Fluent API配置或数据注解,确保外键关系无错误(比如级联操作配置是否合理),避免SaveChanges时出现隐式错误。

额外提示

添加异常捕获后,如果发现是特定错误(比如外键约束冲突、字段长度超限等),可针对性解决:

  • 若为字段长度问题,核对数据库表字段定义与实体类属性的匹配度;
  • 若为并发问题,考虑使用乐观锁或处理并发冲突逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:50:30