sql-server - 如何使用 Entity Framework 处理多种数据库类型支持
问题描述
我需要在项目中支持 MariaDb 和 SqlServer 的迁移。目前,我编辑了由 add-migration 命令创建的迁移文件。您可以看到迁移文件的某些部分。
migrationBuilder.CreateTable(
name: "Tbl1",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1")
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(maxLength: 100, nullable: true),
Measurement = table.Column<string>(maxLength: 100, nullable: true),
},
constraints: table =>
{
table.PrimaryKey("PK_Tbl1", x => x.Id);
});
通过该更改,我的迁移文件可以支持两种数据库类型(MariaDb 和 SqlServer)。但是,我必须为两者设置和使用相同的 ColumnType。我想知道 Entityframework 是否提供了任何最佳实践来支持多种数据库类型?
解决方案
看看Migrations with Multiple Providers,它使用以下两种方法准确讨论了该场景:
两个迁移集
在第一种方法中,您为每个模型更改生成两个迁移。
一种方法是将每个迁移集放在一个单独的程序集中,并在添加两个迁移之间手动切换活动提供程序(和迁移程序集)。
使使用这些工具更容易的另一种方法是创建一个派生自 DbContext 并覆盖活动提供程序的新类型。此类型在设计时添加或应用迁移时使用。
class MySqliteDbContext : MyDbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=my.db");
}
笔记
由于每个迁移集都使用自己的 DbContext 类型,因此这种方法不需要使用单独的迁移程序集。
dotnet ef migrations add InitialCreate --context MyDbContext --output-dir Migrations/SqlServerMigrations
dotnet ef migrations add InitialCreate --context MySqliteDbContext --output-dir Migrations/SqliteMigrations
一套迁移
如果您不喜欢有两组迁移,您可以手动将它们组合成一个可应用于两个提供程序的集合。
注释可以共存,因为提供者会忽略它不理解的任何注释。例如,与 Microsoft SQL Server 和 SQLite 一起使用的主键列可能如下所示。
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn)
.Annotation("Sqlite:Autoincrement", true),
如果操作只能应用于一个提供者,或者它们在提供者之间不同,请使用 ActiveProvider 属性来确定哪个提供者处于活动状态:
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer")
{
migrationBuilder.CreateSequence(
name: "EntityFrameworkHiLoSequence");
}
Pomelo.EntityFrameworkCore.MySql 具体
另请参阅实现当前行为的替代方案以始终抛出,如果已为对象 #982 设置架构以及有关如何处理这种情况的参考,MySQL 和 MariaDB 不知道 SQL Server 架构(例如dbo
)是什么(假设您使用
Pomelo.EntityFrameworkCore.MySql作为提供程序来访问 MariaDB 数据库)。
以下是一些代码选项:
// Throw an exception, if a schema is being used. This is the default.
options.UseMySql(myConnectionString, b => b.SchemaBehavior(MySqlSchemaBehavior.Throw))
// Silently ignore any schema definitions.
options.UseMySql(myConnectionString, b => b.SchemaBehavior(MySqlSchemaBehavior.Ignore))
// Use the specified translator delegate to translate from an input schema and object name to
// an output object name whenever a schema is being used.
options.UseMySql(myConnectionString, b => b.SchemaBehavior(MySqlSchemaBehavior.Translate,
(schema, entity) => $"{schema ?? "dbo"}_{entity}"))
推荐阅读
- javascript - JavaScript/JQuery - 点击 smoot 滚动到 ID
- reactjs - 安装 npm 包时出错(依赖树)
- django - CreateView 未从 urls.py 接收 Kwargs
- android - 如何在 Android 应用上使用 kotlin 发送具有基本身份验证的 POST
- javascript - 如何从 JSON 数据制作 SVG 中的堆栈条形图?
- r - ggplot2 从绝对值值中获取条形图
- python - Python:应用数学运算顺序以括号中的层次结构重新排序字符串
- google-apps-script - 为 Google 表单条目添加批准步骤 -> Google Sheet/Doc
- yarnpkg - 带有纱线浆果的 CLI 凹凸版本号
- sql - 当我尝试在 FROM 之后重命名表时,为什么会出现错误?