Repository: dotnet/efcore
File: src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs (C#)

Code before:
            .Split(["\r\n", "\n"], StringSplitOptions.None);

        var isScript = Options.HasFlag(MigrationsSqlGenerationOptions.Script);
        var hasPendingBatch = false;
        var state = ParsingState.Normal;
        var batchBuilder = new StringBuilder();
        string? pendingTerminator = null;
        foreach (var line in preBatched)
        {
            var trimmed = line.TrimStart();

            if (state == ParsingState.Normal
                && trimmed.StartsWith("GO", StringComparison.OrdinalIgnoreCase)
                && (trimmed.Length == 2
                    || char.IsWhiteSpace(trimmed[2])))
            {
                var batch = batchBuilder.ToString();
                batchBuilder.Clear();

                if (isScript)
                {
                    AppendBatch(batch);
                    if (hasPendingBatch)
                    {
                        pendingTerminator = trimmed + Environment.NewLine + Environment.NewLine;
                    }
                }
                else
                {
                    var count = trimmed.Length >= 4
                        && int.TryParse(trimmed.AsSpan(3), out var specifiedCount)
                            ? specifiedCount
                            : 1;

                    for (var j = 0; j < count; j++)
                    {
                        AppendBatch(batch);
                    }
                }
            }
            else
            {
                for (var i = 0; i < trimmed.Length; i++)
                {
                    var c = trimmed[i];
                    var next = i + 1 < trimmed.Length ? trimmed[i + 1] : '\0';

                    if (state == ParsingState.Normal && c == '-' && next == '-')
                    {
                        goto LineEnd;
                    }

Review comment (performance):
@copilot This is becoming more complex. Take a step back, when isScript is true the code is parsing the SQL to get the batch separators out just to put them back again, perhaps we could avoid parsing altogether instead?

Make sure to also run all SQL Server functional tests to verify

Code after:
            if (!operation.Sql.EndsWith('\n'))
            {
                builder.AppendLine();
            }

            EndStatement(builder, operation.SuppressTransaction);
            return;
        }

        var preBatched = operation.Sql
            .Replace("\\\n", "")
            .Replace("\\\r\n", "")
            .Split(["\r\n", "\n"], StringSplitOptions.None);

        var state = ParsingState.Normal;
        var batchBuilder = new StringBuilder();
        foreach (var line in preBatched)
        {
            var trimmed = line.TrimStart();

            if (state == ParsingState.Normal
                && trimmed.StartsWith("GO", StringComparison.OrdinalIgnoreCase)
                && (trimmed.Length == 2
                    || char.IsWhiteSpace(trimmed[2])))
            {
                var batch = batchBuilder.ToString();
                batchBuilder.Clear();

                var count = trimmed.Length >= 4
                    && int.TryParse(trimmed.AsSpan(3), out var specifiedCount)
                        ? specifiedCount
                        : 1;

                for (var j = 0; j < count; j++)
                {
                    AppendBatch(batch);
                }
            }
            else
            {
                for (var i = 0; i < trimmed.Length; i++)
                {
                    var c = trimmed[i];
                    var next = i + 1 < trimmed.Length ? trimmed[i + 1] : '\0';

                    if (state == ParsingState.Normal && c == '-' && next == '-')
                    {
                        goto LineEnd;
                    }

                    state = state switch