如何使用实体框架处理多数据库类型支持



我需要在项目中支持MariaDb和SqlServer的迁移。目前,我编辑了通过添加迁移命令创建的迁移文件。您可以看到迁移文件的某些部分。

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是否提供了支持多种数据库类型的最佳实践?

看看带有多个提供程序的迁移,它用以下两种方法准确地讨论了这种情况:

两个迁移集

在第一种方法中,您为每个模型更改生成两个迁移。

一种方法是将每个迁移集放在一个单独的程序集中,并在添加两个迁移之间手动切换活动提供程序(和迁移程序集(。

另一种使使用这些工具更容易的方法是创建一个新类型,该类型派生自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

一个迁移集

如果您不喜欢有两组迁移,可以手动将它们组合成一组,可以应用于两个提供程序。

注释可以共存,因为提供程序会忽略它不理解的任何注释。例如,一个同时适用于MicrosoftSQLServer和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");
}

柚子.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}"))

最新更新