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);
}
}
}
}
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);
}
}
}
}