Skip to content

GO batch separator not recognized when block comment contains a single quote #37494

@jenzy

Description

@jenzy

Bug description

EF Core splits SQL Server migration scripts into batches on lines starting with GO. To avoid splitting inside string literals, SqlServerMigrationsSqlGenerator tracks whether it is inside a quoted string using a quoted boolean that toggles on single quotes ('). This quote-tracking logic was introduced in #34917.

The implementation does not handle standard SQL block comments (/* ... */). If a block comment contains a single quote, the quoted state is incorrectly toggled even though the quote is inside a comment. Since there is no matching closing quote, quoted remains true across subsequent lines.

As a result, a later GO line is not recognized as a batch separator and is sent to SQL Server as literal text, causing:

Microsoft.Data.SqlClient.SqlException: Incorrect syntax near 'go'.

This commonly occurs in stored procedure scripts where a header block comment contains a ' character above a CREATE PROCEDURE statement.

Your code

// Program.cs
using Microsoft.EntityFrameworkCore;

using var db = new AppDbContext();
db.Database.Migrate();

public class AppDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=localhost;Database=BugRepro;Integrated Security=true;TrustServerCertificate=true");
    }
}



// Migrations/20260112114024_Repro.cs
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace EFCoreBugRepro.Migrations
{
    public partial class Repro : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            // This causes Microsoft.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near 'go'.
            // Removing the ' or adding another one fixes it.
            migrationBuilder.Sql("""
                /* It's a procedure */
                create procedure dbo.proc1 as select 1;
                go
                
                /* Another one */
                create procedure dbo.proc2 as select 2;
            """);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
        }
    }
}

Stack traces

Unhandled exception. Microsoft.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near 'go'.
   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, SqlCommand command, 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.Execute(IReadOnlyList`1 migrationCommands, IRelationalConnection connection, MigrationExecutionState executionState, Boolean beginTransaction, Boolean commitTransaction, Nullable`1 isolationLevel)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.<>c.<ExecuteNonQuery>b__3_1(DbContext _, ValueTuple`6 s)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IReadOnlyList`1 migrationCommands, IRelationalConnection connection, MigrationExecutionState executionState, Boolean commitTransaction, Nullable`1 isolationLevel)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.MigrateImplementation(DbContext context, String targetMigration, MigrationExecutionState state, Boolean useTransaction)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.<>c.<Migrate>b__20_1(DbContext c, ValueTuple`4 s)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
   at Program.<Main>$(String[] args) in E:\Temp\Ef\EFCoreBugRepro\Program.cs:line 4
ClientConnectionId:b9596174-9bd9-495b-a72b-fbea59692dff
Error Number:102,State:1,Class:15

Verbose output


EF Core version

10.0.1

Database provider

Microsoft.EntityFrameworkCore.SqlServer

Target framework

.NET 10

Operating system

Windows 11

IDE

No response

Metadata

Metadata

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions