【问题标题】:Unable to create object error in dotnet ef migrations for MySql DbContext, but works for Sqlite DbContext无法在 MySql DbContext 的 dotnet ef 迁移中创建对象错误,但适用于 Sqlite DbContext
【发布时间】:2020-11-24 11:14:14
【问题描述】:

我为一个新的 ASP.Net Core 应用创建了 2 个 DbContexts。

https://github.com/jonasarcangel/IdentityMigrationsForMySql/tree/master/IdentityMigrationsForMySql/Server/Data

它们都派生自同一个 ApplicationDbContext 基类,唯一的区别是 OnConfiguring 覆盖,其中使用 UseMySql 而不是 UseSqlite,遵循 post about multiple providers 中的建议。

SqliteDbContext.cs 有这个:

        protected override void OnConfiguring(DbContextOptionsBuilder options)
        {
#if DEBUG_EF
            options.UseSqlite("DataSource=");
#endif
        }

MySqlDbContext.cs 有这个:

        protected override void OnConfiguring(DbContextOptionsBuilder options)
        {
#if DEBUG_EF
            options.UseMySql("Server=");
#endif
        }

运行了以下命令:

dotnet ef migrations add InitialCreate --context MySqlDbContext --output-dir Migrations/MySql --configuration DebugEf

返回的错误是:

无法创建“MySqlDbContext”类型的对象。对于不同的 设计时支持的模式,请参阅 https://go.microsoft.com/fwlink/?linkid=851728

但是,以下使用 Sqlite 上下文的命令是成功的。

dotnet ef migrations add InitialCreate --context SqliteDbContext --output-dir Migrations/Sqlite --configuration DebugEf

【问题讨论】:

  • 请不要链接到属于该问题的主要代码的外部存储库。如果链接断开,问题应该仍然可以理解。
  • 对于链接中断或(更有可能)链接代码发生剧烈变化的问题来说,这还不足以解决问题。
  • 存储库是专门为这个问题制作的。这不是我需要修复的实际项目。
  • 不过,所有 Stack Overflow 问题都应该是独立的。

标签: asp.net entity-framework asp.net-core


【解决方案1】:

这是因为在您的 ConfigureServices 方法中,您显式配置了 SqliteDbContext:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<SqliteDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            ...
        }

如果您将代码更改为 AddDbContext&lt;MySqlDbContext&gt;,这会成功创建迁移,但随后会破坏 Sqlite 构建。

如果您继续阅读您链接的文章,它们会描述如何解决此问题:

在您的应用程序中,您应该继续使用MyDb。然而,对于 EF 来确定使用哪个迁移,你必须调用 services.GetService&lt;T&gt; 其中 T 是子类之一(而不是 MyDb)。

因此,在Startup.ConfigureServices 中注册子类:

// Configure database 
switch (config.DbProvider.ToLower()) {
case "sqlite": {
    services.AddDbContext<MyDb>(options => { options.UseSqlite(config.DbConnString); });
    services.AddDbContext<SqliteMyDb>(options => { options.UseSqlite(config.DbConnString); });
}
    break;
case "postgres": {
    services.AddDbContext<MyDb>(options => options.UseNpgsql(config.DbConnString));
    services.AddDbContext<NpgsqlMyDb>(options => options.UseNpgsql(config.DbConnString));
}
    break;
default: {
    throw new Exception($"DbProvider not recognized: {config.DbProvider}");
} } 

然后,在 Startup.Configure 中进行迁移:

void ProcessDb<T>()
where T : MyDb {
    using var db = services.GetService<T>();
    db.Database.Migrate();

    // ... perform other startup tasks with db }

switch (config.DbProvider.ToLower()) {
    case "sqlite": {
        ProcessDb<SqliteMyDb>();
        break;
    }
    case "postgres": {
        ProcessDb<NpgsqlMyDb>();
        break;
    }
    default: {
        throw new Exception();
    } } 

总而言之,对于每一个额外的提供者,添加一个子类,一个两行的案例 在 ConfigureServices 中,以及在 Configure 中的一个案例。

【讨论】:

  • 我不知道 Startup.ConfigureServices 也被称为“dotnet ef 迁移”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多