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

.NET MAUI打包APK后EF Core无法创建数据库引发应用崩溃问题

.NET MAUI Release APK运行时EF Core数据库不创建、操作崩溃修复

这个问题和EF Core与.NET MAUI的兼容性无关,核心原因是Android Release构建默认开启的托管代码裁剪(Trimmer/Linker)会移除SQLite、EF Core运行时通过反射调用、未被静态引用的类型与方法,调试模式默认关闭代码裁剪所以功能运行完全正常。另外你当前DbContext的实现存在初始化时序问题,Release模式下JIT编译优化会放大这个问题,直接触发崩溃。

按以下步骤逐一修复:

  • 调整DbContext初始化逻辑,移除构造函数内的数据库操作
    你当前在DataContext构造函数里直接调用Database.EnsureCreated()存在时序问题:构造函数执行时OnConfiguring还未完成数据库路径与连接配置,Release模式下编译优化会导致空引用或路径未初始化异常。同时不要把SQLite的初始化逻辑放在DbContext构造函数里,提前到应用启动入口执行。
    修正后的DataContext代码:
using Microsoft.EntityFrameworkCore;
using MedbaseRec.Models;

namespace MedbaseRec.Utils
{
    public class DataContext : DbContext
    {
        public DbSet<QuestionPack> QuestionPacks { get; set; }
        public DbSet<Question> Questions { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string dbPath = Path.Combine(FileSystem.AppDataDirectory, "medbaseapplica.db3");
            optionsBuilder.UseSqlite($"Filename={dbPath}");
        }
    }
}

打开项目下的MauiProgram.cs,在CreateMauiApp方法最开头添加SQLite全局初始化,同时把DbContext注册到依赖注入容器,避免手动new实例带来的配置不一致问题:

public static MauiApp CreateMauiApp()
{
    // 全局初始化SQLite提供器
    SQLitePCL.Batteries_V2.Init();

    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });

    // 注册DbContext
    builder.Services.AddDbContext<DataContext>();

    return builder.Build();
}

数据库创建逻辑放到应用启动完成后执行,比如在App.xaml.cs的OnStart生命周期方法中调用,避免启动时序冲突:

protected override async void OnStart()
{
    base.OnStart();
    using var scope = Handler.MauiContext.Services.CreateScope();
    var db = scope.ServiceProvider.GetRequiredService<DataContext>();
    await db.Database.EnsureCreatedAsync();
}
  • 配置代码裁剪规则,保留EF Core与SQLite相关程序集
    右键Android平台项目,编辑项目文件(.csproj),在Release配置对应的PropertyGroup节点下调整Linker规则,避免依赖被裁剪:
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
  <!-- 首次验证可临时设为None,确认问题后改回SdkOnly减少包体积 -->
  <AndroidLinkMode>SdkOnly</AndroidLinkMode>
</PropertyGroup>

<ItemGroup>
  <!-- 声明以下程序集不被裁剪 -->
  <TrimmerRootAssembly Include="Microsoft.EntityFrameworkCore" />
  <TrimmerRootAssembly Include="Microsoft.EntityFrameworkCore.Sqlite" />
  <TrimmerRootAssembly Include="SQLitePCLRaw.batteries_v2" />
  <TrimmerRootAssembly Include="SQLitePCLRaw.core" />
  <TrimmerRootAssembly Include="SQLitePCLRaw.provider.e_sqlite3" />
  <TrimmerRootAssembly Include="MedbaseRec" /> <!-- 替换为你自己的核心业务项目程序集名 -->
</ItemGroup>

排查阶段可以先把AndroidLinkMode设为None重新打包,如果APK运行正常,就能100%确认是代码裁剪导致的问题,后续再逐步收紧裁剪规则缩小包体积。

  • 补全依赖与权限检查
    • 给Android项目单独安装SQLitePCLRaw.provider.e_sqlite3NuGet包,版本和EF Core SQLite依赖的版本完全一致,避免Release构建时原生SQLite库libe_sqlite3.so没有被打包进APK。
    • 检查Platforms/Android/AndroidManifest.xml,确认配置了应用私有目录的读写权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Android 13及以上版本不需要申请全存储权限即可访问应用私有目录,但部分厂商定制ROM权限管控逻辑特殊,缺失权限会直接导致数据库文件创建失败。

  • 验证打包内容
    生成Release APK后,把后缀改为zip解压,检查lib/<对应CPU架构>目录下是否存在libe_sqlite3.so文件,如果不存在说明NuGet包版本冲突或者构建配置有问题,需要统一SQLite相关依赖的版本后重新构建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:24:18