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

.NET MAUI项目从SQLite取数据触发NullReferenceException

.NET MAUI SQLite空引用异常排查与修复

你遇到的System.NullReferenceException出现在QuizViewModel.GetQuestionsAsync()调用_dBService.GetQuestionsAsync()时,核心原因大概率是嵌入式数据库资源加载失败,或者数据库初始化逻辑存在异步未等待的问题。以下是具体排查步骤和修复方案:

1. 检查嵌入式数据库的资源配置

这是最常见的问题根源:

  • 右键项目Data文件夹下的cbt.db文件 → 「属性」,将「生成操作」设置为嵌入的资源。如果没设置,程序无法从程序集里读取到这个文件。
  • 验证资源名称是否正确:GetManifestResourceStream的参数必须是完整的资源路径,格式为「项目命名空间.文件夹名.文件名」。比如你的项目命名空间是CBT,文件在Data文件夹,参数应为"CBT.Data.cbt.db"。如果不确定实际名称,可以在LoadDB方法里添加代码打印所有资源名:
    var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
    Debug.WriteLine("所有嵌入式资源:" + string.Join(", ", assembly.GetManifestResourceNames()));
    
    运行后查看输出,找到cbt.db对应的正确名称,替换掉原代码里的参数。

2. 修复LoadDB方法的空值防护

原代码中如果资源加载失败,stream会为null,直接调用stream.CopyTo就会触发空引用。修改LoadDB:

public void LoadDB()
{
    if (!File.Exists(DBPath))
    {
        var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
        using Stream? stream = assembly.GetManifestResourceStream("CBT.Data.cbt.db");

        if (stream == null)
        {
            Debug.WriteLine("错误:无法找到嵌入式数据库资源,请检查资源名称和生成操作设置");
            return;
        }

        using MemoryStream? memoryStream = new();
        stream.CopyTo(memoryStream);
        File.WriteAllBytes(DBPath, memoryStream.ToArray());
        Debug.WriteLine("数据库文件已成功复制到本地");
    }
}

3. 修正数据库初始化的异步逻辑

DBService构造函数里的_database.CreateTableAsync<Question>()是异步操作,但没有await,这会导致表还没创建完成就执行查询。由于构造函数不能标记为async,我们可以把表创建逻辑移到GetQuestionsAsync里:

public async Task<List<Question>> GetQuestionsAsync()
{
    // 确保表存在后再查询
    await _database.CreateTableAsync<Question>();
    return await _database.Table<Question>().ToListAsync();
}

4. 规避集合索引越界风险

QuizViewModel.CreateAsync里直接访问viewModel.Questions[viewModel._currentQuestionIndex],如果查询回来的问题集合为空或者数量不足,会触发新的异常。添加判断逻辑:

[RelayCommand]
public static async Task<QuizViewModel> CreateAsync(IDBService dBService)
{
    var viewModel = new QuizViewModel(dBService);
    await viewModel.GetQuestionsAsync();

    // 安全设置当前问题
    if (viewModel.Questions.Count > 0)
    {
        var targetIndex = viewModel._currentQuestionIndex >= viewModel.Questions.Count ? 0 : viewModel._currentQuestionIndex;
        viewModel.CurrentQuestion = viewModel.Questions[targetIndex];
    }
    else
    {
        Debug.WriteLine("警告:未获取到任何问题数据");
        viewModel.CurrentQuestion = null;
    }

    return viewModel;
}

最后验证

做完以上修改后,运行程序,查看输出日志:

  • 如果数据库资源加载成功,会打印「数据库文件已成功复制到本地」;
  • 如果资源找不到,会打印对应的错误提示,再根据日志调整资源名称或生成操作设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:17:03