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.79k stars 3.19k forks source link

Error in Generated Migration Script for dotnet-ef 8.0.11 #35132

Open costinbanu opened 2 hours ago

costinbanu commented 2 hours ago

We have a dotnet project that we upgraded from dotnet 7 to dotnet 8. We also updated dotnet-ef from 7.0.2.0 to 8.0.11 in the pipeline that we use. This change has introduced a bug when generating migration scripts

Generated SQL script with version 8.0.11

IF NOT EXISTS (
    SELECT * FROM [__EFMigrationsHistory]
    WHERE [MigrationId] = N'myMigrationName'
)
BEGIN
    EXEC sp_rename N'[dbo].[oldTableName]', N'newTableName', 'OBJECT';
    DECLARE @defaultSchema sysname = SCHEMA_NAME();
    EXEC(N'ALTER SCHEMA [' + @defaultSchema + N'] TRANSFER [dbo].[newTableName];');
END;

IF NOT EXISTS (
    SELECT * FROM [__EFMigrationsHistory]
    WHERE [MigrationId] = N'migrationName2'
)
BEGIN
    EXEC sp_rename N'[dbo].[oldTableName2]', N'newTableName2', 'OBJECT';
    DECLARE @defaultSchema sysname = SCHEMA_NAME();
    EXEC(N'ALTER SCHEMA [' + @defaultSchema + N'] TRANSFER [dbo].[newTableName2];');
END;

This fails because the variable @defaultSchema is declared twice in the same SQL batch. Let's have a look at the old version SQL output:

Generated SQL script with version 7.0.20

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'migrationName2')
BEGIN
    EXEC sp_rename N'[dbo].[oldTableName2]', N'newTableName2';
    DECLARE @defaultSchema sysname = SCHEMA_NAME();
    EXEC(N'ALTER SCHEMA [' + @defaultSchema + N'] TRANSFER [dbo].[newTableName2];');
END;
GO

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'migrationName')
BEGIN
    EXEC sp_rename N'[dbo].[oldTableName]', N'newTableName';
    DECLARE @defaultSchema sysname = SCHEMA_NAME();
    EXEC(N'ALTER SCHEMA [' + @defaultSchema + N'] TRANSFER [dbo].[newTableName];');
END;
GO

Here you can see that besides the order of the migrations and some formatting, the new version is lacking the sql batch separator GO which is, essentially, the source of the problem

Steps to reproduce

Expected behavior

The script is executed successfully

Actual behavior

The deployment fails / Azure DevOps pipeline step SqlAzureDacpacDeployment fails with message ##[error]The variable name '@defaultSchema' has already been declared. Variable names must be unique within a query batch or stored procedure.Check out how to troubleshoot failures at https://aka.ms/sqlazuredeployreadme#troubleshooting-

Provider and version information

EF Core version: 8.0.11 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 8.0 Operating system: private Azure DevOps pipeline agent running on Windows 10 x64 IDE:

costinbanu commented 2 hours ago

And the same error happens also when using dotnet-ef version 9.0.0