dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.66k stars 3.15k forks source link

Migrate from EFCore5 to EFCore6 - my first migration adds annotations for some properties in every single table. Why? #27121

Closed ssteiner closed 1 year ago

ssteiner commented 2 years ago

So, I wanted to give .NET 6 a spin for my .NET 5 programs. My EFCore code is based on EFCore5.

so I changed the output target to net6, and updated the EFCore libraries from the 5.x versions to the 6.0.1 version. It all builds fine. Then as a test I wanted to see what happens if I do a code first migration. So I added a single property to a single of my model classes. Then added a migration (`Add-Migration migrationName).

Worked as expected, I do see the AddColumn in the Up Override and the DropColumn in the Down override.

And then.. I see an AlterColumn three statements for every table (well, nearly). Most of my model classes derive from a base class that defined the column order in attributes. And I get an AlterColum for every Name, Description and Id column on every table where the model derivces from BaseObject

public partial class BaseObject: BaseIdObject
    {

        [Column(Order = 1)]
        [Required]
        public string Name { get; set; }

        [Column(Order = 2)]
        public string Description { get; set; }

        public bool? IsDefault { get; set; }
    }

public class BaseIdObject
    {
        [Key, Column(Order = 0)]
        public Guid Id { get; set; }
    }

So, for a model class UserProfile which derivces from BaseObject, I get these three AlterColums

migrationBuilder.AlterColumn<string>(
                name: "Name",
                table: "UserProfiles",
                type: "nvarchar(max)",
                nullable: false,
                oldClrType: typeof(string),
                oldType: "nvarchar(max)")
                .Annotation("Relational:ColumnOrder", 1);

            migrationBuilder.AlterColumn<string>(
                name: "Description",
                table: "UserProfiles",
                type: "nvarchar(max)",
                nullable: true,
                oldClrType: typeof(string),
                oldType: "nvarchar(max)",
                oldNullable: true)
                .Annotation("Relational:ColumnOrder", 2);

            migrationBuilder.AlterColumn<Guid>(
                name: "Id",
                table: "UserProfiles",
                type: "uniqueidentifier",
                nullable: false,
                oldClrType: typeof(Guid),
                oldType: "uniqueidentifier")
                .Annotation("Relational:ColumnOrder", 0);

(and corresponding stuff with .OldAnnotation() on the down method):

migrationBuilder.AlterColumn<string>(
                name: "Name",
                table: "UserProfiles",
                type: "nvarchar(max)",
                nullable: false,
                oldClrType: typeof(string),
                oldType: "nvarchar(max)")
                .OldAnnotation("Relational:ColumnOrder", 1);

            migrationBuilder.AlterColumn<string>(
                name: "Description",
                table: "UserProfiles",
                type: "nvarchar(max)",
                nullable: true,
                oldClrType: typeof(string),
                oldType: "nvarchar(max)",
                oldNullable: true)
                .OldAnnotation("Relational:ColumnOrder", 2);

            migrationBuilder.AlterColumn<Guid>(
                name: "Id",
                table: "UserProfiles",
                type: "uniqueidentifier",
                nullable: false,
                oldClrType: typeof(Guid),
                oldType: "uniqueidentifier")
                .OldAnnotation("Relational:ColumnOrder", 0);

So... the way I understand it, it changes the colum order, but Id remains at 0, Name at 1, description at 2.. so what it was originally.

Am I missing something or all these statements completely redundant? And if so, why are they being created in the first place.

Include provider and version information

EF Core version: 6.0.1 Database provider: (Microsoft.EntityFrameworkCore.SqlServer) Target framework: (.NET 6.0) Operating system: Windows 11 Pro IDE: (Visual Studio 2022 16.3)

ajcvickers commented 2 years ago

@ssteiner This is by-design. EF Core 6.0 now includes and tracks the column order in the migrations model. When these change (in this case, from unknown values to specific values), EF generates AlterColumn commands to reflect this. Some databases/database providers are then able to ensure the columns are in the correct order--for example, MySQL and SQLite. SQL Server does not have this capability, so the result is a no-op on the database side.