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 -> 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; } // <--- 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!;
}
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:
Game
has a field called NumberCode
, never has it been NumberCodeDisplay
)Migration_1
migration. The resulting migration file [timestamp]_Migration_1.cs
is correct: 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
) 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
{
/// <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") // <------ Here
.HasColumnType("decimal(18,2)");
b.Property<int>("YearReleased")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Games");
});
// ...
}
}
This is probably due to me adding/removing some migrations after Migration_1
, notably there were a couple "Migration_2
s" 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.