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

.NET MAUI中EF Core v7在iOS上SQLite无法打开数据库文件问题

.NET MAUI + EF Core 7 iOS SQLite 数据库异常解决

问题场景

在.NET MAUI项目中使用Entity Framework Core v7.0.14,Android模拟器上数据库运行正常,但iOS平台执行Database.Migrate()时抛出以下异常:

Microsoft.Data.Sqlite.SqliteException: 'SQLite Error 14: 'unable to open database file''

原路径生成逻辑通过拼接../Library生成数据库路径,确认目录已存在但仍报错;修改为使用FileSystem.AppDataDirectory后,首次删除应用运行仍抛原异常,后续启动Database.Migrate()出现其他异常。

问题分析

  1. 路径处理不规范:iOS中手动使用相对路径../Library可能导致路径解析或权限问题,MAUI提供了统一的跨平台数据目录API,无需手动拼接
  2. 初始化时机错误:在DbContext构造函数中调用Database.Migrate(),此时应用依赖或路径可能未完全就绪
  3. SQLite初始化滞后:SQLitePCL.Batteries_V2.Init()调用位置过晚,导致SQLite环境未准备好就执行数据库操作

解决方案

1. 统一跨平台数据库路径获取

使用MAUI官方推荐的FileSystem.AppDataDirectory获取数据目录,避免手动拼接路径:

public static class DatabaseConstants
{
    public static string GetDatabasePath()
    {
        const string databaseName = "StudentsDatabaseSQLite.db3";
        // MAUI跨平台数据目录,iOS下对应~/Library/Application Support(拥有读写权限)
        var baseDirectory = FileSystem.AppDataDirectory;
        // 冗余保障:确保目录存在(FileSystem.AppDataDirectory默认已存在)
        Directory.CreateDirectory(baseDirectory);
        return Path.Combine(baseDirectory, databaseName);
    }
}

2. 调整EF Core初始化时机

移除DbContext构造函数中的Database.Migrate(),改为在应用启动阶段执行迁移,确保依赖环境就绪:

修改DbContext

public class DatabaseContext : DbContext
{
    public DbSet<Student> Students { get; set; }

    public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
    {
        // 移除构造函数内的Database.Migrate()调用
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            string connectionString = $"Filename={DatabaseConstants.GetDatabasePath()};Mode=ReadWriteCreate";
            optionsBuilder.UseSqlite(connectionString)
                          .EnableDetailedErrors(true);
        }
    }
}

在应用启动时执行迁移

修改MauiProgram.cs,提前初始化SQLite并在应用就绪后执行迁移:

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

// 提前初始化SQLitePCL,确保环境就绪
SQLitePCL.Batteries_V2.Init();

// 注册DbContext到依赖注入容器
var dbPath = DatabaseConstants.GetDatabasePath();
builder.Services.AddDbContext<DatabaseContext>(options => 
    options.UseSqlite($"Filename={dbPath};Mode=ReadWriteCreate"));

var app = builder.Build();

// 应用启动后,通过依赖注入获取DbContext并执行迁移
using var scope = app.Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
try
{
    dbContext.Database.Migrate();
}
catch (Exception ex)
{
    // 可添加日志或错误提示逻辑
    Console.WriteLine($"数据库迁移失败:{ex.Message}");
}

return app;

3. 完善连接字符串配置

在连接字符串中添加Mode=ReadWriteCreate参数,确保SQLite自动创建不存在的数据库文件,并以读写模式打开:

string connectionString = $"Filename={dbPath};Mode=ReadWriteCreate";

4. 验证步骤

  1. 从iOS模拟器中删除应用
  2. 执行dotnet clean清理项目
  3. 重新生成并运行项目,检查迁移是否正常执行,数据库是否可正常访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:21:00