asp.net - 无法在 MySql DbContext 的 dotnet ef 迁移中创建对象错误,但适用于 Sqlite DbContext
问题描述
我为一个新的 ASP.Net Core 应用程序创建了 2 个 DbContexts。
它们都派生自同一个 ApplicationDbContext 基类,唯一的区别是 OnConfiguring 覆盖,其中使用 UseMySql 而不是 UseSqlite,遵循本文中关于多个提供程序的建议。
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
解决方案
这是因为在您的ConfigureServices
方法中,您明确配置了 SqliteDbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SqliteDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
...
}
如果您将代码更改为 ,这将成功创建迁移AddDbContext<MySqlDbContext>
,但它会破坏 Sqlite 构建。
如果您继续阅读您链接的文章,他们将描述如何解决此问题:
在您的应用程序中,您应该继续使用
MyDb
. 但是,要让 EF 确定要使用哪个迁移,您必须调用services.GetService<T>
where 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 中添加一个案例。
推荐阅读
- macos - 在哪里可以找到现代 Mac OS X Cocoa 文档?
- java - 强制 React-Native webview 将 url 加载为移动设备?
- java - 使用方法时日历给出错误的年份
- php - PHP获取最后一个特定日期
- apache-spark - 无法在 MacOS 中将 Python 3 设置为 Apache spark 的默认版本
- python - Keras如何将输入形状更改为3维
- xamarin - 如何更改
- css - 创建两个垂直按钮反应原生
- python - 在 Windows 10 和虚拟机 Ubuntu 中获得相同操作的不同结果
- docker - 尝试在 Windows 10 上到达 Docker Express API 端点的连接重置错误