测试实体框架迁移中的架构更改

问题描述 投票:0回答:2

背景

我正在使用管道来管理 .net 核心项目。 在我的管道中,在构建阶段,我运行

dotnet ef migrations script --context "MyDbContext" --project "./MySolution/MyDataProject/" --output "./migrationScript.sql" --idempotent
来生成脚本,这些脚本稍后可以针对各种测试、登台和生产环境数据库运行以同步架构(我在非生产环境中使用与生产环境中相同的方法)以确保这些脚本经过测试)。

据我了解,这些脚本不是根据数据库上下文生成的,而是使用项目中已经定义的迁移;这些迁移是通过

add
命令定义的(例如
dotnet ef migrations add vNext --context "MyDbContext" --project "./MySolution/MyDataProject/"
)。 因此,开发人员可能会对数据模型进行更改,忘记运行
migrations add
命令来添加新的迁移,从而创建一个无法更新架构的解决方案。

问题

有没有办法测试迁移是否与代码同步/是否需要新的迁移?

围绕解决方案的思考

我希望在 dbContext 没有更改时运行

dotnet ef migrations add
不会有任何输出;所以我可以测试是否存在新文件,并在错过该文件时终止管道(在 git 中不检查任何内容;因此新的迁移不会保留/留给开发人员手动重新运行)。

查看可用选项,只有

add
remove
list
script
;因此执行此检查没有任何明显的意义。

我可以在管道中的

add
命令之前运行
script
命令,以确保它已运行;但未来的运行可能会出现问题,因为如果添加的迁移未推送到 git,则下一次迭代将不会意识到此迁移。 如果我将这个新的迁移推送到 git 就可以解决这个问题;但随后会产生一个新问题,即每个构建都会产生新的迁移,因此我们将有很多多余的混乱/这种方法将不可持续。

我能想到的最好的解决方案是运行

add
命令,然后检查生成的脚本以查看
Up
Down
方法在函数体内是否有任何内容;但这感觉很老套;我不确定这是否足够(例如,
.Designer.cs
文件中的方法是否会发生变化,而不会在
.cs
文件中的向上/向下产生任何内容?)。

我确信微软会为此在工具集中创建一些东西;但我正在努力寻找它。预先感谢您的任何帮助。

现有/类似答案

entity-framework .net-core entity-framework-migrations
2个回答
3
投票

似乎适用于我尝试过的一些简单测试用例的方法是添加测试迁移,然后检查迁移目录中的

<ContextName>ModelSnapshot.cs
文件是否已更改。

该文件仅在核心迁移被修改时才出现更改。


0
投票

您可以在自动化测试中生成迁移并验证它是否为空。为此:

  1. 添加套餐
    Microsoft.EntityFrameworkCore.Design

确保 csproj 中的引用如下所示:

        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="VERSION" />

以下版本不正确

        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="VERSION">
            <PrivateAssets>all</PrivateAssets>
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
  1. 您可以在代码中生成迁移,如下所示:
        var startupAssembly = <..TODO..>;
        var dbContextAssembly = <..TODO..>;

        // Magic code deduced from dotnet-ef code
        // similar things happen when you run 'dotnet ef migrations add'

#pragma warning disable EF1001
        var reporter = new OperationReporter(new OperationReportHandler());
        var designTimeServicesBuilder =
            new DesignTimeServicesBuilder(dbContextAssembly, startupAssembly, reporter, Array.Empty<string>());
        var services = designTimeServicesBuilder.CreateServiceCollection(DbContext);
        services.AddEntityFrameworkDesignTimeServices();
        var sp = services.BuildServiceProvider();

        using var scope = sp.CreateScope();
        var scaffolder = scope.ServiceProvider.GetRequiredService<IMigrationsScaffolder>();
#pragma warning restore EF1001

        var migration = scaffolder.ScaffoldMigration(
            "TestMigration",
            "TestNamespace");
  1. 您可以使用以下正则表达式检测是否存在丢失的迁移:
        var match = Regex.Match(migration,
            @"protected override void Up\(MigrationBuilder migrationBuilder\)\s*\{(.*)\}.*" + // catch Up method body
            @"protected override void Down\(MigrationBuilder migrationBuilder\)\s*\{(.*)\}" + // catch down method body
            @"\s*}\s*}", // catch closing class and namespace - it should not be included in down method body group
            RegexOptions.Multiline |
            RegexOptions.Singleline);

        var upCode = match.Groups[1].Value;
        var downCode = match.Groups[2].Value; 

        Assert.True(string.IsNullOrEmpty(upCode.Trim()));
        Assert.True(string.IsNullOrEmpty(downCode.Trim()));

因此,您将永远不必记住迁移,也不需要修改管道。

© www.soinside.com 2019 - 2024. All rights reserved.