【问题标题】:EF Core Migration with multiple provider always runs SQL Server scripts具有多个提供程序的 EF Core 迁移始终运行 SQL Server 脚本
【发布时间】:2018-09-22 06:49:12
【问题描述】:

我首先使用的是 EF Core 代码,但在使用多个数据库提供程序(SQL Server 和 MySql)时遇到了问题。 即使我选择使用 MySql DB 提供程序,也会使用 SQL 服务器迁移文件。

查看示例project

【问题讨论】:

标签: c# .net entity-framework entity-framework-core


【解决方案1】:

在我的情况下,我对两个提供程序使用相同的迁移,但有时我需要手动对迁移文件进行一些更改。例如为两个提供者添加注释(或将某些字段的类型如 varchar 更改为 nvarchar)。

Id = table.Column<int>(nullable: false)
           .Annotation("MySql:ValueGeneratedOnAdd", true)
           .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),

对我来说没问题

【讨论】:

  • 我不想使用这种方法。拥有两个迁移集更加干净。
  • @pantonis 你是对的,这只是别人可以使用的另一种方法
【解决方案2】:

使用 Entity Framework 核心编写特定于提供程序的迁移、数据库初始化程序和服务可能是一项艰巨的任务。使用AdaptiveClient 可以大大简化流程。 AdaptiveClient 是一个与Autofac 一起使用的实用程序,用于针对多个数据库提供程序或传输配置服务层。 AdaptiveClient.EntityFrameworkCore 是一个附加组件,包括用于使用 Entity Framework Core 的实用程序。简而言之,这是 AdaptiveClient 的工作原理:

IMigrationContext 是一个占位符接口,允许您将 DbContext 与特定提供程序(MSSQL、MySql 等)相关联,以便创建迁移。 IDbContextOptions 是一个占位符接口,允许您关联特定于您的提供者的 DbContextOptions 实现。 RegistrationHelper 是一个实用程序,可简化向 Autofac 注册组件的过程。 RegisterMigrationContext 是一种您可以调用以轻松注册特定于提供程序的迁移上下文的方法。

要创建特定于提供程序的迁移,您需要为每个要定位的数据库提供程序创建一个类。这些类派生自您的 DbContext 并实现 IMigrationContext(没有成员):

public class MyDbContext_MSSQL : MyDbContext, IMigrationContext
{
    public MyDbContext_MSSQL(DbContextOptions options) : base(options)
    {

    }
}   


public class MyDbContext_MySQL : MyDbContext, IMigrationContext
{
    public MyDbContext_MySQL(DbContextOptions options) : base(options)
    {

    }
}

上面的例子是完整的——你不需要编写任何额外的代码。您不需要为每个提供者创建单独的 DbContext(除非您希望这样做)。您需要为每个提供程序创建一个类的原因是,当您运行 dotnet ef migrations add... 时,EF 会反映您的程序集以找到正确的 DbContext。

创建包装DbContextOptions 并实现IDbContextOptions 的类:

public class DbContextOptions_MSSQL : IDbContextOptions
{
    public DbContextOptions Options { get; set; }

    public DbContextOptions_MSSQL(string connectionString)
    {
        DbContextOptionsBuilder builder = new DbContextOptionsBuilder();
        builder.UseSqlServer(connectionString);
        Options = builder.Options;
    }
}


public class DbContextOptions_MySQL : IDbContextOptions
{
    public DbContextOptions Options { get; set; }

    public DbContextOptions_MySQL(string connectionString)
    {
        DbContextOptionsBuilder builder = new DbContextOptionsBuilder();
        builder.UseMySql(connectionString);
        Options = builder.Options;
    }
}

使用 AdaptiveClient RegistrationHelper 向 Autofac 注册您的类:

registrationHelper.RegisterMigrationContext<Database.Db_MSSQL>(API_Name.MyAPI, DataBaseProviderName.MSSQL);
registrationHelper.RegisterMigrationContext<Database.Db_MySQL>(API_Name.MyAPI, DataBaseProviderName.MySQL);

registrationHelper.RegisterDbContextOptions<DbContextOptions_MSSQL>(DataBaseProviderName.MSSQL);
registrationHelper.RegisterDbContextOptions<DbContextOptions_MySQL>(DataBaseProviderName.MySQL);    

在上面的代码中,API_Name 只是一个常量,它解析为像“MyApplicationName”这样的简单字符串。与 DataBaseProviderName.MSSQL 和 .MySQL 相同。它们是解析为“MSSQL”或“MySQL”的字符串常量。

现在,这是最重要的部分:正如您使用“MSSQL”或“MySQL”等键注册应用程序的组件一样,您也使用这些相同的常量为您的应用程序注册连接字符串。

这允许 Autofac 仅根据当前用于应用程序的连接字符串来解析正确的特定于提供程序或特定于传输的组件。您可以阅读整个过程here

您可以在Zamagon Demo 中查看完整的工作示例。该演示说明了用于集成测试的迁移、数据库初始化程序和删除和重新创建场景。

【讨论】:

    猜你喜欢
    • 2020-05-29
    • 2021-01-16
    • 1970-01-01
    • 2020-02-17
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多