-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
Per this comment from @ajcvickers, 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:
public class Thing
{
public int Id { get; set; }
[Column(Order = 3)]
public string Name { get; set; }
}
public class ThingContext : DbContext
{
public ThingContext(DbContextOptions<ThingContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Thing>()
.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'.
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