.netasp.net-coreentity-framework-coreazure-sql-databaseef-core-8.0

sqlcmd fails with Incorrect syntax near ';' after upgrading to .NET 8


We upgraded from .NET 6 to .NET 8 and now the dotnet-ef tool generates newlines in between, which the sqlcmd doesn't like. It's an Azure SQL database with compatibility level 150.

dotnet ef migrations script --project hidden --startup-project hidden  
       --output AppDbContext.sql --context AppDbContext --verbose --idempotent
sqlcmd -S "hidden" -d "hidden" -U "hidden" -P "hidden" -i "D:\AppDbContext.sql"

Msg 102, Level 15, State 1, Server hidden, Line 11
Incorrect syntax near ';'

I ran the SQL manually and it seems like it doesn't the empty BEGIN...END:

IF NOT EXISTS (
    SELECT * FROM [Historical].[EFMigration]
    WHERE [MigrationId] = N'20210814000018_AddSPHedgeReport'
)
BEGIN




END;
GO

EF 6 didn't use to generate this.

using Microsoft.EntityFrameworkCore.Migrations;

namespace hidden
{
    public partial class AddSPHedgeReport : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn<string?>(
                name: "FixedProperty",
                schema: "Reports",
                table: "SectionColumn",
                nullable: true);
            migrationBuilder.RunScripts("20210813");

        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropColumn(
                name: "FixedProperty",
                schema: "Reports",
                table: "SectionColumn");
        }
    }
}

Another one that fails:

#nullable disable

using Microsoft.EntityFrameworkCore.Migrations;

namespace hidden
{
    public partial class AuditTables : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.RunScripts("20220920");
        }

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

Here is what ScriptHelper does:

public static class ScriptHelper
{
    public static void RunScripts(this MigrationBuilder migrationBuilder, string version)
    {
        var assembly = Assembly.GetExecutingAssembly();
        var resourceNames = assembly.GetManifestResourceNames().Where(str => str.EndsWith(version + ".sql"));
        foreach (var resourceName in resourceNames)
        {
            using (var stream = assembly.GetManifestResourceStream(resourceName))
            using (var reader = new StreamReader(stream))
            {
                var sql = reader.ReadToEnd();
                migrationBuilder.Sql(sql);
            }
        }
    }
}

Solution

  • Using the Trim() method effectively removes leading and trailing whitespace from SQL scripts, enhancing their compatibility and preventing format-related errors during execution.

    public static class ScriptHelper
    {
        public static void RunScripts(this MigrationBuilder migrationBuilder, string version)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var resourceNames = assembly.GetManifestResourceNames().Where(str => str.EndsWith(version + ".sql"));
            foreach (var resourceName in resourceNames)
            {
                using var stream = assembly.GetManifestResourceStream(resourceName);
                using var reader = new StreamReader(stream);
                //Removes white spaces or characters specified in an array of characters from the beginning and end of a string.
                var sql = reader.ReadToEnd().Trim();
                    
                if (!string.IsNullOrWhiteSpace(sql))
                {
                    migrationBuilder.Sql(sql);
                }
            }
        }
    }