Preserve batch terminators in migration scripts for SQL operations with GO separators#37810
Merged
AndriySvyryd merged 8 commits intomainfrom Feb 27, 2026
Merged
Conversation
…n transactions In GenerateSqlScript, always emit batch terminator (GO for SQL Server) after BEGIN TRANSACTION and between individual commands, even within a transaction. This ensures that SQL statements like CREATE VIEW, which must be the first statement in a batch, work correctly in generated migration scripts. Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix migration sql script output for create view command
Emit batch terminators between commands within transactions in migration scripts
Feb 27, 2026
test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsInfrastructureSqlServerTest.cs
Outdated
Show resolved
Hide resolved
Address review feedback: instead of isolating BEGIN TRANSACTION and COMMIT in their own GO-terminated batches, keep them in the same batch as their adjacent commands. GO separators now only appear between individual commands within a transaction. Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
…enerator for script mode Instead of changing Migrator.GenerateSqlScript, fix at the source: SqlServerMigrationsSqlGenerator.Generate(SqlOperation) now embeds batch terminators directly in the command text when generating for scripts (Options.HasFlag(Script)), producing a single MigrationCommand with GO separators preserved. For non-script execution, behavior is unchanged (separate MigrationCommands per batch). Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot
AI
changed the title
Emit batch terminators between commands within transactions in migration scripts
Preserve batch terminators in migration scripts for SQL operations with GO separators
Feb 27, 2026
src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
Outdated
Show resolved
Hide resolved
…parators in script mode Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
AndriySvyryd
approved these changes
Feb 27, 2026
test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs
Outdated
Show resolved
Hide resolved
test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
Outdated
Show resolved
Hide resolved
…base class Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
Outdated
Show resolved
Hide resolved
…r Can_generate_up_and_down_scripts Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This pull request fixes an issue where Script-Migration strips GO batch separators from custom SQL within transactions, breaking statements like CREATE VIEW that must be the first statement in a batch.
Changes:
- Modified
SqlServerMigrationsSqlGenerator.Generate(SqlOperation)to skip GO parsing in script mode and pass raw SQL through as-is, preserving batch terminators literally - Added test case
SqlOperation_handles_go_in_script_with_suppress_transactionto verify GO separators (includingGO Ncount syntax) are preserved in script generation mode - Updated baselines to reflect the new behavior where embedded GO separators are preserved
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs |
Added early return in Script mode to pass raw SQL through without GO parsing, preserving batch terminators |
test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs |
Added test verifying GO separators are preserved in script mode with suppressTransaction |
test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsInfrastructureSqlServerTest.cs |
Updated baselines for two tests to reflect preserved GO separators in Migration4 |
6 tasks
roji
approved these changes
Feb 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Script-Migrationstrips GO batch separators from custom SQL within transactions, breaking statements likeCREATE VIEWthat must be the first statement in a batch.Before: GO-separated batches within a single
SqlOperationare split into separateMigrationCommands, whichGenerateSqlScriptthen joins with newlines (not GO) inside transactionsAfter: In script generation mode, the GO parsing is skipped entirely and the raw SQL is passed through as-is, preserving all GO separators (including
GO Ncount syntax) in the final script output. A line ending is appended only if the SQL doesn't already end with one, avoiding double newlines.Changes
SqlServerMigrationsSqlGenerator.Generate(SqlOperation): When generating for a script (Options.HasFlag(MigrationsSqlGenerationOptions.Script)), skip GO parsing entirely and pass the raw SQL through as a singleMigrationCommandviabuilder.Append. A trailing line ending is conditionally appended only if the SQL doesn't already end with\n. This preserves GO separators as-is in the generated script. For non-script execution, behavior is unchanged — GO separators still split into separate commands with count expansion as before.Can_generate_up_and_down_scriptsandCan_generate_up_and_down_scripts_noTransactionsto reflect the raw SQL pass-through for Migration4 (which contains embedded GO separators withsuppressTransaction: true).SqlOperation_handles_go_in_script_with_suppress_transactiontest that verifiesmigrationBuilder.SqlwithsuppressTransaction: trueand SQL containing multiple GO separators (includingGO 2with count) correctly preserves batch terminators in script generation mode.This approach fixes the problem at the SQL generator level with minimal complexity — since script mode was parsing GO separators out just to reconstruct them, we avoid the parsing altogether and let the raw SQL flow through directly.
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.