EF Core会随机更改列名,尽管模型没有更改。

huangapple go评论76阅读模式
英文:

EF Core randomly renames a column, despite no changes to model

问题

在我的ASP.Net Core MVC应用程序中,我有一个简单的Game类,以及两个用于发出请求或在视图上显示的GameRequestGameResponse类(在下面的片段中)。

在添加新的迁移(与无关的功能相关)时,我注意到EF Core添加了一个.RenameColumn()操作,具体来说是从Games.NumberCodeDisplay -> Games.NumberCode,这是毫无意义的。Games从一开始就没有NumberCodeDisplay列,甚至在创建它的上一个迁移中也没有

奇怪的是,这个错误的列名与GameResponse的列名相同,尽管它没有出现在应用程序的DbContext中。

// GameModels.cs

public class Game
{
    public int Id { get; set; }

    public string Name { get; set; } = string.Empty;
    public string NameCode { get; set; } = string.Empty;
    public decimal NumberCode { get; set; } // <--- this property has *never* changed
    public int YearReleased { get; set; }
}

public class GameRequest
{
    public string Name { get; set; } = string.Empty;
    public string NameCode { get; set; } = string.Empty;
    public decimal NumberCode { get; set; }
    public int YearReleased { get; set; }
}

public class GameResponse
{
    public int Id { get; set; }

    public string Name { get; set; } = string.Empty;
    public string NameCode { get; set; } = string.Empty;
    public string NumberCodeDisplay { get; set; } = string.Empty;

    public int YearReleased { get; set; }

    public static string GetNumberCodeDisplay(decimal numberCode)
    {
        // ...
    }
}
// migration file generated after `add-migration` 

public partial class AddField_Game_CoverImageUrl : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: "NumberCodeDisplay",
            table: "Games",
            newName: "NumberCode");
    }

    /// <inheritdoc />
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: "NumberCode",
            table: "Games",
            newName: "NumberCodeDisplay");
    }
}
// AppDbContext.cs

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options)
    {
    }

    public DbSet<Song> Songs { get; set; } = default!;
    public DbSet<Game> Games { get; set; } = default!;
}
英文:

In my ASP.Net Core MVC app, I have a simple Game class, plus 2 GameRequest and GameResponse classes (in snippets below) that are used for making requests, or for displaying on a view.

On adding a new migration (for an unrelated feature), I noticed EF Core adding a .RenameColumn() operation, specifically from Games.NumberCodeDisplay -&gt; Games.NumberCode, which makes no sense. The Games table never had the NumberCodeDisplay column in the first place, even in the previous migration where it was created.

Curiously, this incorrect column name is the same as that of GameResponse's despite it not being in the app's DbContext.

// GameModels.cs

public class Game
{
	public int Id { get; set; }

	public string Name { get; set; } = string.Empty;
	public string NameCode { get; set; } = string.Empty;
	public decimal NumberCode { get; set; } // &lt;--- this property has *never* changed
	public int YearReleased { get; set; }
}

public class GameRequest
{
	public string Name { get; set; } = string.Empty;
	public string NameCode { get; set; } = string.Empty;
	public decimal NumberCode { get; set; }
	public int YearReleased { get; set; }
}

public class GameResponse
{
	public int Id { get; set; }

	public string Name { get; set; } = string.Empty;
	public string NameCode { get; set; } = string.Empty;
	public string NumberCodeDisplay { get; set; } = string.Empty;
	public int YearReleased { get; set; }

	public static string GetNumberCodeDisplay(decimal numberCode)
	{
		// ...
	}
}
// migration file generated after `add-migration` 

public partial class AddField_Game_CoverImageUrl : Migration
{
    /// &lt;inheritdoc /&gt;
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: &quot;NumberCodeDisplay&quot;,
            table: &quot;Games&quot;,
            newName: &quot;NumberCode&quot;);
    }

    /// &lt;inheritdoc /&gt;
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: &quot;NumberCode&quot;,
            table: &quot;Games&quot;,
            newName: &quot;NumberCodeDisplay&quot;);
    }
}
// AppDbContext.cs

public class AppDbContext : DbContext
{
	public AppDbContext(DbContextOptions&lt;AppDbContext&gt; options)
		: base(options)
	{
	}

	public DbSet&lt;Song&gt; Songs { get; set; } = default!;
	public DbSet&lt;Game&gt; Games { get; set; } = default!;
}

答案1

得分: 0

我找到了问题,尽管我不太清楚最初是什么原因导致的。

我忘记添加之前创建表的迁移文件(我们称之为Migration_1;帖子中的空迁移将是Migration_2),以及模型快照文件。但我发现的是:

  • C#模型类始终是正确的(Game有一个名为NumberCode的字段,从未是NumberCodeDisplay
  • 我添加了Migration_1迁移。生成的迁移文件[timestamp]_Migration_1.cs是正确的:
protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Games",
        columns: table => new
        {
            Id = table.Column<int>(type: "int", nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
            NameCode = table.Column<string>(type: "nvarchar(max)", nullable: false),
            NumberCode = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
            YearReleased = table.Column<int>(type: "int", nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Games", x => x.Id);
        });
}
  • 但是,迁移设计器文件[timestamp]_Migration_1.Designer.cs)出现错误,错误地指定应创建一个具有NumberCodeDisplay列的Games表(在应用到实际数据库之前):
partial class Add_Game
{
    /// <inheritdoc />
    protected override void BuildTargetModel(ModelBuilder modelBuilder)
    {
#pragma warning disable 612, 618
        modelBuilder
            .HasAnnotation("ProductVersion", "7.0.7")
            .HasAnnotation("Relational:MaxIdentifierLength", 128);

        SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);

        modelBuilder.Entity("MyProject.Models.Game", b =>
            {
                b.Property<int>("Id")
                    .ValueGeneratedOnAdd()
                    .HasColumnType("int");

                SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));

                b.Property<string>("Name")
                    .IsRequired()
                    .HasColumnType("nvarchar(max)");

                b.Property<string>("NameCode")
                    .IsRequired()
                    .HasColumnType("nvarchar(max)");

                b.Property<decimal>("NumberCodeDisplay") // <------ 这里
                    .HasColumnType("decimal(18,2)");

                b.Property<int>("YearReleased")
                    .HasColumnType("int");

                b.HasKey("Id");

                b.ToTable("Games");
            });
        // ...
    }
}
  • 但是在数据库本身中,Games表确实具有正确的NumberCode列名称。

这可能是因为在Migration_1之后我添加/删除了一些迁移,特别是在我决定剪切掉所有模型更改(针对与此无关的功能)并测试一个空迁移(当前的Migration_2)之前有一些“Migration_2”。但我不能确定。

目前,我只是手动编辑了Migration_1的设计器文件和模型快照文件,然后进一步的迁移不会再次重命名。

英文:

I found the problem, though I don't really know what caused it in the first place.

I forgot to add the previous migration files where I created the table (let's call it Migration_1; the empty migration in the post would be Migration_2), and the model snapshot file. But what I've found is that:

  • The C# model class is always correct (Game has a field called NumberCode, never has it been NumberCodeDisplay)
  • I added the Migration_1 migration. The resulting migration file [timestamp]_Migration_1.cs is correct:
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: &quot;Games&quot;,
                columns: table =&gt; new
                {
                    Id = table.Column&lt;int&gt;(type: &quot;int&quot;, nullable: false)
                        .Annotation(&quot;SqlServer:Identity&quot;, &quot;1, 1&quot;),
                    Name = table.Column&lt;string&gt;(type: &quot;nvarchar(max)&quot;, nullable: false),
                    NameCode = table.Column&lt;string&gt;(type: &quot;nvarchar(max)&quot;, nullable: false),
                    NumberCode = table.Column&lt;decimal&gt;(type: &quot;decimal(18,2)&quot;, nullable: false),
                    YearReleased = table.Column&lt;int&gt;(type: &quot;int&quot;, nullable: false)
                },
                constraints: table =&gt;
                {
                    table.PrimaryKey(&quot;PK_Games&quot;, x =&gt; x.Id);
                });
        }
  • However, the migration designer file ([timestamp]_Migration_1.Designer.cs) for some reason incorrectly specified that a Games table with the NumberCodeDisplay column should be created (before being applied to the actual database):
    partial class Add_Game
    {
        /// &lt;inheritdoc /&gt;
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation(&quot;ProductVersion&quot;, &quot;7.0.7&quot;)
                .HasAnnotation(&quot;Relational:MaxIdentifierLength&quot;, 128);

            SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);

            modelBuilder.Entity(&quot;MyProject.Models.Game&quot;, b =&gt;
                {
                    b.Property&lt;int&gt;(&quot;Id&quot;)
                        .ValueGeneratedOnAdd()
                        .HasColumnType(&quot;int&quot;);

                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property&lt;int&gt;(&quot;Id&quot;));

                    b.Property&lt;string&gt;(&quot;Name&quot;)
                        .IsRequired()
                        .HasColumnType(&quot;nvarchar(max)&quot;);

                    b.Property&lt;string&gt;(&quot;NameCode&quot;)
                        .IsRequired()
                        .HasColumnType(&quot;nvarchar(max)&quot;);

                    b.Property&lt;decimal&gt;(&quot;NumberCodeDisplay&quot;) // &lt;------ Here
                        .HasColumnType(&quot;decimal(18,2)&quot;);

                    b.Property&lt;int&gt;(&quot;YearReleased&quot;)
                        .HasColumnType(&quot;int&quot;);

                    b.HasKey(&quot;Id&quot;);

                    b.ToTable(&quot;Games&quot;);
                });
            // ...
        }
    }

  • But in the database itself, the Games table does have the correct NumberCode column name.
    EF Core会随机更改列名,尽管模型没有更改。

This is probably due to me adding/removing some migrations after Migration_1, notably there were a couple "Migration_2s" before I decided to cut out all the model changes (for an unrelated feature) and test out an empty migration (the current Migration_2). But I can't be sure.

For now, I've just manually edited Migration_1's designer file, and the model snapshot file, and then further migrations wouldn't have the rename again.

huangapple
  • 本文由 发表于 2023年6月19日 22:50:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507780.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定