First migration after upgrading to .NET 6 doesn't rebuild indexes
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
Per [this comment from @ajcvickers](https://github.com/dotnet/efcore/issues/27121#issuecomment-1008748945), the first created migration after upgrading to .NET 6 generates code to set column order annotations (This only happens if the `[Column(Order = X)]` attribute is used.)
**The problem is, this newly generated code doesn't handle existing indexes that must be removed before the `ALTER COLUMN` SQL can be executed.**
Here's my model and context. Note the unique index on Name, which I did simply to create an index to reproduce the problem:
```c#
public class Thing
{
public int Id { get; set; }
[Column(Order = 3)]
public string Name { get; set; }
}
public class ThingContext : DbContext
{
public ThingContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasIndex(p => p.Name)
.IsUnique();
base.OnModelCreating(modelBuilder);
}
}
```
I have attached a repro. If you open it and run `update-database`, you'll get an exception:
```
Failed executing DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
DECLARE @var0 sysname;
SELECT @var0 = [d].[name]
FROM [sys].[default_constraints] [d]
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Thing]') AND [c].[name] = N'Name');
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [Thing] DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE [Thing] ALTER COLUMN [Name] nvarchar(450) NULL;
Microsoft.Data.SqlClient.SqlException (0x80131904): The index 'IX_Thing_Name' is dependent on column 'Name'.
ALTER TABLE ALTER COLUMN Name failed because one or more objects access this column.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean isAsync, Int32 timeout, Boolean asyncWrite)
at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName)
at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:565e69e2-f740-4b3b-9c1a-f8ed61957fbf
Error Number:5074,State:1,Class:16
The index 'IX_Thing_Name' is dependent on column 'Name'.
```
[WebApplication1.zip](https://github.com/dotnet/efcore/files/8544016/WebApplication1.zip)
The way we solved this problem for now is to create the migration, and delete everything from the main migration file (20220422204914_Second), while leaving everything in the snapshot (ThingContextModelSnapshot.cs) intact. This seems to make EF think it did what it needed to do. Is that a valid solution?
Or is the better solution to remove the `[Column(Order = x)]` attribute before creating the new migration?
Or is there a way to turn off the feature?
EF Core version: 6.0.0
Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer)
Target framework: (e.g. .NET 6.0)
Operating system: Windows 10 (up to date)
IDE: Visual Studio 2022 17.1.5
Contributor guide
Assessment
This issue has not been assessed yet.