关于实体框架 6:如何将 EF6 迁移定位为仅在 SQL Server 上执行?

How can I target a EF6 migration to only execute on SQL Server?

我想确保在 SQL Server 中启用特定功能。我目前正在使用 EF6 迁移来生成我的更改脚本。我正在对 SQL Server 2012 和 SQL Server CE 4 使用我的迁移(用于我的映射的基本单元测试)。 SQL Server CE 不支持我要启用的特定功能。

如何创建仅适用于 SQL Server 的迁移?

这里是有问题的迁移:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public partial class EnableSnapshotIsolation : DbMigration
{
    public override void Up()
    {

        Sql(@"  ALTER DATABASE CURRENT
                SET READ_COMMITTED_SNAPSHOT ON", true);

        Sql(@"  ALTER DATABASE CURRENT
                SET ALLOW_SNAPSHOT_ISOLATION ON", true);
    }


    public override void Down()
    {
        Sql(@"  ALTER DATABASE CURRENT
                SET READ_COMMITTED_SNAPSHOT OFF", true);

        Sql(@"  ALTER DATABASE CURRENT
                SET ALLOW_SNAPSHOT_ISOLATION OFF", true);
    }
}

注意:我们会手动部署更改脚本。一个人打开一个 SSMS 窗口并执行脚本。作为构建打包过程的一部分,我使用 update-database -script 命令提供了一个更改脚本。所以 EF 没有创建数据库。


经过一番摸索,我发现迁移本身没有办法抑制基于数据库类型的迁移。但是,您可以为特定的提供者实现自己的迁移器。

我的解决方案涉及像这样更新我的配置类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory ="Data\\\\Migrations";
        SetSqlGenerator("System.Data.SqlClient", new SqlMigrator());
    }

    private class SqlMigrator : SqlServerMigrationSqlGenerator
    {
        public override IEnumerable<MigrationStatement> Generate(
            IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken)
        {
            var statements = new List<MigrationStatement>
            {
                new MigrationStatement
                {
                    Sql ="ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT ON",
                    SuppressTransaction = true
                },
                new MigrationStatement
                {
                    Sql ="ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON",
                    SuppressTransaction = true
                }
            };
            statements.AddRange(base.Generate(migrationOperations, providerManifestToken));
            return statements;
        }
    }
}

注意:这当然会在 2012 年之前的 Sql Server 版本上失败,所以让你的脚本尽可能地强大,因为它需要设置这些标志。这适用于我的具体情况。