.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,确认配置了应用私有目录的读写权限:
- 给Android项目单独安装
<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
相关产品推荐
相关产品推荐

