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

.NET MAUI中EF Core增改表时迁移异常问题求助

.NET MAUI + EF Core SQLite 跨平台迁移解决方案(Windows/Android)

核心问题分析

你遇到的"表未找到"异常,本质是未正确应用EF Core迁移:

  • EnsureCreated()仅能创建数据库和表,但不会生成/应用迁移记录,后续修改表结构时无法同步更新现有数据库
  • Migrate()需要提前生成迁移文件,而EF Core CLI工具仅在Windows平台支持完整操作,需先在Windows生成迁移再移植到多平台

步骤1:在Windows平台生成迁移文件

所有迁移文件必须先在Windows环境生成,再同步到MAUI项目中:

  1. 打开Windows PowerShell,进入MAUI项目根目录
  2. 若未安装EF Core工具,执行:
    dotnet tool install --global dotnet-ef
    
  3. 生成初始迁移(对应现有数据库结构):
    dotnet ef migrations add InitialCreate --project YourMauiProjectName
    
  4. 后续修改表结构(新增/重命名表)后,生成新迁移:
    dotnet ef migrations add AddNewTable_Or_RenameTable
    
  5. 确认项目中生成的Migrations文件夹及所有迁移文件已被包含在MAUI项目中(默认会自动包含,可检查.csproj文件确认)

步骤2:修正DbContext配置(避免映射错误)

你的DbContext中存在大小写不一致的DbSet命名(如itemComboResponses),EF Core默认会映射到同名小写表,容易引发"表未找到"问题,建议统一为PascalCase并添加Fluent API明确映射:

namespace bluelotus360.Com.MauiSupports.LocalDB
{
    public class LocalDatabaseContext : DbContext
    {
        // 统一DbSet命名为PascalCase,与实体类保持一致
        public DbSet<IncomingStrings> IncomingStrings { get; set; }
        public DbSet<ItemComboResponses> ItemComboResponses { get; set; }
        public DbSet<RequestQueueItem> RequestQueueItems { get; set; }
        public DbSet<StockAsAt> StockAsAts { get; set; }
        public DbSet<AddressMasterModel> AddressMasterModels { get; set; }
        public DbSet<ItemMasterModel> ItemMasterModels { get; set; }
        public DbSet<UserMessageObject> UserMessageObjects { get; set; }
        public DbSet<PrintQueueItem> PrintQueueItems { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                string connectionDb = $"Filename={DBPath.GetPath("erp_dbase_v1.db")}";
                optionsBuilder.UseSqlite(connectionDb);
            }
        }

        // 用Fluent API明确表名映射,避免EF默认规则冲突
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<ItemComboResponses>().ToTable("ItemComboResponses");
            modelBuilder.Entity<PrintQueueItem>().ToTable("PrintQueueItems");
            // 其他实体可按需添加
        }
    }
}

步骤3:正确执行迁移的启动代码

替换原有的EnsureCreated()/直接new DbContext的代码,改用依赖注入执行迁移,确保跨平台兼容性:

// 注册DbContext,统一配置连接字符串
builder.Services.AddDbContext<LocalDatabaseContext>(options =>
{
    string connectionDb = $"Filename={DBPath.GetPath("erp_dbase_v1.db")}";
    options.UseSqlite(connectionDb);
});

// 创建服务作用域,执行迁移
using var scope = builder.Services.BuildServiceProvider().CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<LocalDatabaseContext>();
try
{
    // Migrate()会自动创建数据库(若不存在)并应用所有未执行的迁移
    dbContext.Database.Migrate();
}
catch (Exception ex)
{
    // 开发环境可添加日志或调试输出
    System.Diagnostics.Debug.WriteLine($"迁移执行失败:{ex.Message}");
    // 极端情况(如旧数据库损坏)可删除重建(仅开发环境使用)
    // dbContext.Database.EnsureDeleted();
    // dbContext.Database.EnsureCreated();
}

步骤4:Android平台特殊配置

  1. 数据库路径验证:确保DBPath.GetPath()返回Android私有存储路径,示例实现:
    public static class DBPath
    {
        public static string GetPath(string dbName)
        {
            return DeviceInfo.Platform switch
            {
                DevicePlatform.Android => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), dbName),
                DevicePlatform.WinUI => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), dbName),
                _ => throw new NotSupportedException("当前平台未支持")
            };
        }
    }
    
  2. 清除旧数据:测试Android时,建议卸载旧应用再安装,避免残留的旧数据库文件导致迁移冲突

额外排查点(解决"表未找到")

  • 重命名表需手动修改迁移文件:EF Core不会自动生成重命名表的代码,需手动修改迁移文件的Up()/Down()方法:
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameTable(
            name: "OldTableName",
            newName: "NewTableName");
    }
    
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameTable(
            name: "NewTableName",
            newName: "OldTableName");
    }
    
  • 禁止混合使用EnsureCreated()和Migrate():EnsureCreated()会跳过迁移表__EFMigrationsHistory的创建,导致后续Migrate()无法识别数据库版本,引发结构不匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 16:14:50