Database.Migrate() 创建数据库但不创建表,EF 和 .NET Core 2

Database.Migrate() creating database but not tables, EF & .NET Core 2

这个问题已经被问过几次了,但是 solutions/documentation 中的 none 对我有用。

场景 - 我需要从头开始构建一个数据库并通过代码迁移对其进行编辑,根据文档,下面的行应该从 DbContext/ModelBuilder.

创建数据库
_dbContext.Database.Migrate();

然而,这只是创建数据库本身和表的 none。如果我 运行 下面的,

_dbContext.Database.EnsureCreated();

数据库和所有表都已创建,但是这不是一个选项,因为我需要进一步编辑迁移。我在 Migrate 行之后直接尝试了下面的代码,但 pendingMigrations 始终为 0。

var pendingMigrations = _dbContext.Database.GetAppliedMigrations().ToList();
        if (pendingMigrations.Any())
        {
            var migrator = _dbContext.Database.GetService<IMigrator>();
            foreach (var targetMigration in pendingMigrations)
                migrator.Migrate(targetMigration);
        }

我在这里遗漏了什么吗? Database.Migrate() 不应该像创建数据库一样创建表吗?

注意 - 在测试中,我在尝试另一种方法之前删除了数据库。

另一个经典案例,就是在此处发布问题后半小时才找到答案,苦苦挣扎了一两天。发布我的解决方案以防其他人遇到类似问题。

TLDR - _dbContext.Database.Migrate(); 不创建迁移。

基本上,dbContext.Database.EnsureCreated() 不关心迁移,这就是它生成完整数据库 inc 表的原因(但是当然你不能迁移)。

_dbContext.Database.Migrate(); 应用迁移并创建数据库(如果不存在)但是如果没有迁移则不会创建表。

基本上我有一个项目作为资源,我试图从用户生成的新应用程序中复制项目,但因为我从来没有 运行 资源项目中的任何迁移,所以没有任何东西可以迁移。 运行 资源项目 PMC 中的 Add-Migration Initial 为项目提供了初始迁移文件,因此当我 运行 在新数据库上迁移时,它知道要创建哪些表。

在我的例子中,我有多个项目并且 DesignTimeDbContextFactory 指向一个 MigrationsAssembly 但在启动时 sqlOptions 不是。

所以当 DI 创建时 DbContext 它不知道有待处理的迁移。

您可以使用以下方法检查待处理的迁移 dbContext.Database.GetPendingMigrations();Migrate(); 之前检查它是否找到迁移

解决方案是在 sqlOptions

中添加迁移 MigrationsAssembly
 services.AddDbContext<BM_OCR_DbContext>(options =>
                {
                    options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection"),
                    sqlServer => sqlServer.MigrationsAssembly("BM.OCR.Server"));
                });

另一种方法 - 在 EF 迁移项目中创建扩展方法。它可以在没有 sqlServer.MigrationsAssembly() 方法的情况下工作。

namespace Project.Data;
{
    public static class Extensions
    {
        public static void AddEntityFramework(this IServiceCollection services, IConfiguration configuration)
        {
            var cnn = configuration.GetConnectionString("DefaultConnection");
            services.AddDbContext<AppDbContext>(opt => opt.UseSqlServer(cnn));
        }
    }
}

然后在Startup.cs中使用它

services.AddEntityFramework(Configuration);