Skip to content

Forward EF migration connection string to the dotnet-ef tool resource - #18452

Merged
Mitch Denny (mitchdenny) merged 5 commits into
mainfrom
copilot/fix-db1-migrations-start-issue
Jul 14, 2026
Merged

Forward EF migration connection string to the dotnet-ef tool resource#18452
Mitch Denny (mitchdenny) merged 5 commits into
mainfrom
copilot/fix-db1-migrations-start-issue

Conversation

Copilot AI commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #18375

Description

AddEFMigrations(...).WithReference(<db>) failed to apply migrations with The ConnectionString property has not been initialized. because the connection string attached to the migration resource never reached the hidden dotnet-ef tool resource.

AddEFMigrationCommands only copied environment annotations from the startup project, and did so eagerly during AddEFMigrations — before .WithReference(<db>) is called. When the database is referenced on the migration resource (not the project), ConnectionStrings__<db> was never forwarded to the design-time process.

// db1 is referenced on the migration resource, so its connection string lives there — not on `api`.
api.AddEFMigrations("db1-migrations", "MyDb1Context")
   .RunDatabaseUpdateOnStart()
   .WithReference(db1).WaitFor(db1);

Changes

  • EFResourceBuilderExtensions.AddEFMigrationCommands: add a lazy WithEnvironment callback on the tool resource that forwards the migration resource's own environment callbacks at start time. This captures ConnectionStrings__<db> from .WithReference(<db>), which is added after the command-wiring runs (the eager project-env copy can't see it).
  • Test: ToolResourceInheritsConnectionStringFromMigrationReference asserts ef-tool-<name> resolves ConnectionStrings__<db> from the migration reference.

Note: the ASPNETCORE_URLS / portForServing line in the issue is a non-fatal DCP substitution warning (endpoint env is unused by design-time EF); the connection-string failure is the actual blocker addressed here.

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

…ol resource

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 24, 2026 02:05
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 24, 2026 02:33
Copilot AI changed the title [WIP] Fix db1-migrations resource in SQL Playground to start correctly Forward EF migration connection string to the dotnet-ef tool resource Jun 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where AddEFMigrations(...).WithReference(<db>) failed with The ConnectionString property has not been initialized. The root cause is that AddEFMigrationCommands only copied environment annotations from the startup project (eagerly, before .WithReference(<db>) runs), so the connection string declared on the migration resource never reached the hidden dotnet-ef tool resource.

The fix adds a lazy WithEnvironment callback on the tool resource that forwards the migration resource's own EnvironmentCallbackAnnotations at start time, capturing ConnectionStrings__<db> that is added after the command-wiring runs. I verified the forwarded callbacks are evaluated both in run mode (via StartEfToolResourceAsyncExecutionConfigurationBuilder.WithEnvironmentVariablesConfig()) and when the env is resolved directly, that EFMigrationResource inherits from ContainerResource (so .WithReference adds the expected annotation), and that the lazy callback iterates the migration resource's annotations (not the tool's), so there is no recursion or duplicate-application on the same resource.

Changes:

  • Add a lazy WithEnvironment callback to the dotnet-ef tool resource that forwards the migration resource's environment callbacks at start time.
  • Add regression test ToolResourceInheritsConnectionStringFromMigrationReference verifying ef-tool-<name> resolves ConnectionStrings__<db> from the migration reference.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Aspire.Hosting.EntityFrameworkCore/EFResourceBuilderExtensions.cs Adds the lazy env-forwarding callback so the design-time dotnet-ef process receives the migration resource's connection string.
tests/Aspire.Hosting.EntityFrameworkCore.Tests/AddEFMigrationsTests.cs Adds a regression test (and a minimal IResourceWithConnectionString test resource) asserting the connection string flows to the tool resource.

I did not identify any concrete, high-confidence issues to comment on. The change is small and well-scoped, the regression test exercises the exact code path that was broken, and the surrounding behavior (run vs. publish, project vs. migration env, tool-resource isolation) checks out.

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18452

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18452"

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI review requested due to automatic review settings June 24, 2026 21:24
@AndriySvyryd
Andriy Svyryd (AndriySvyryd) force-pushed the copilot/fix-db1-migrations-start-issue branch from 70e19ae to ff811e7 Compare June 24, 2026 21:24
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

@AndriySvyryd

Copy link
Copy Markdown
Member

PR Testing Report

PR Information

Artifact Version Verification

  • Expected Commit: ff811e7
  • Installed Version: N/A — built and ran the PR branch source at head commit (local repo, 13.5.0-dev)
  • Status: ✅ Verified (local HEAD == origin PR head == ff811e7)

Changes Analyzed

Files Changed

  • src/Aspire.Hosting.EntityFrameworkCore/EFResourceBuilderExtensions.cs — Modified: adds a lazy WithEnvironment callback on the hidden dotnet-ef tool resource that forwards the migration resource's own env callbacks (notably ConnectionStrings__<db> from .WithReference(<db>)).
  • tests/Aspire.Hosting.EntityFrameworkCore.Tests/AddEFMigrationsTests.cs — Added regression test ToolResourceInheritsConnectionStringFromMigrationReference.

Change Categories

  • CLI changes detected
  • Hosting integration changes (EF Core)
  • Dashboard changes
  • CI infrastructure changes
  • VS Code extension changes
  • Test changes

Why templates couldn't be used

This behavior is not expressible via aspire new templates — no template wires AddEFMigrations(...).WithReference(<db>).RunDatabaseUpdateOnStart() against a real SQL Server. The faithful repro is the SqlServerEndToEnd playground, which is exactly the bug scenario. Tested with locally-built PR bits (Docker available for the SQL containers).

Test Scenarios Executed

Scenario 1: End-to-end migration on start (run mode) — the exact fixed scenario

Objective: Verify dotnet-ef receives ConnectionStrings__<db> from .WithReference(<db>) on the migration resource and applies migrations, instead of failing with The ConnectionString property has not been initialized.
Coverage Type: Happy path (end-to-end)
Status: ✅ Passed

Setup note: The playground's sql2 is a real AddAzureSqlServer (not a container), which cannot provision locally and stalled run-on-start orchestration on the first run (the ef-tool executable was never created in DCP; db1 stayed empty). To exercise the fix end-to-end without Azure, sql2 was temporarily given .RunAsContainer() (local edit, reverted after testing — working tree confirmed clean).

Steps:

  1. Built and ran SqlServerEndToEnd.AppHost from PR head with both SQL servers as containers.
  2. Waited for db1/db2 containers to become healthy and db1-migrations/db2-migrations (both .WithReference(db).RunDatabaseUpdateOnStart()) to run.
  3. Queried each database's __EFMigrationsHistory and table list via sqlcmd in the container.
  4. Checked AppHost log for the connection-string error.

Evidence:

  • db1 applied migration: 20260511233127_Initial; tables: __EFMigrationsHistory, Entries.
  • db2 applied migration: 20260511233305_Initial; tables: __EFMigrationsHistory, Entries.
  • The ConnectionString property has not been initialized.absent from AppHost output.

Observations:

  • Both EF migration resources forwarded their connection string to the dotnet-ef tool and applied migrations successfully against real SQL Server.

Scenario 2: Regression unit test

Objective: Assert ef-tool-<name> resolves ConnectionStrings__<db> from the migration reference.
Coverage Type: Unit / regression
Status: ✅ Passed (and verified fix-dependent)

Steps:

  1. Ran ToolResourceInheritsConnectionStringFromMigrationReference.
  2. Counter-check: temporarily disabled the forwarding block → test failed (ConnectionStrings__db1 not found, keys present: OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY, ASPNETCORE_FORWARDEDHEADERS_ENABLED, HTTP_PORTS); restored → passed.

Observations:

  • The test deterministically covers the changed code path.

Unhappy-path / boundary coverage

Second migration resource (db2-migrations) referencing a different database (db2)
Status: ✅ Passed — db2 migration applied independently with its own ConnectionStrings__db2, confirming per-migration-resource forwarding with no cross-wiring or missing string on the second resource.

Summary

Scenario Status Notes
E2E migration on start (db1) ✅ Passed 20260511233127_Initial applied; Entries table created
E2E migration on start (db2) ✅ Passed 20260511233305_Initial applied; Entries table created
Regression unit test ✅ Passed Verified failing without the fix
No connection-string error ✅ Passed Error string absent from AppHost output

Overall Result

✅ PR VERIFIED

The fix correctly forwards ConnectionStrings__<db> from .WithReference(<db>) on an EF migration resource to the hidden dotnet-ef tool resource. Migrations apply successfully end-to-end against real SQL Server in run mode, and the original The ConnectionString property has not been initialized. failure no longer occurs.

Notes / Recommendations

  • Testing required temporarily containerizing the playground's sql2 (Azure SQL) to avoid an unrelated Azure provisioning dependency; this is an environment/playground characteristic, not a defect in the PR. The temporary edit was reverted.

@AndriySvyryd
Andriy Svyryd (AndriySvyryd) force-pushed the copilot/fix-db1-migrations-start-issue branch from ff811e7 to 82bd75e Compare June 24, 2026 21:51
@AndriySvyryd
Andriy Svyryd (AndriySvyryd) marked this pull request as ready for review June 24, 2026 21:51
Copilot AI review requested due to automatic review settings June 24, 2026 21:51
@github-actions

Copy link
Copy Markdown
Contributor

Tests selector (audit mode)

The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement.

2 / 98 test projects · 2 jobs, from 10 changed files.

Selected test projects (2 / 98)

Aspire.Hosting.EntityFrameworkCore.Tests, Aspire.Playground.Tests

Selected jobs (2)

extension-e2e, typescript-api-compat


How these were chosen — grouped by what changed

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/AppHost.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db1Migrations/20260511233127_Initial.Designer.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db1Migrations/20260511233127_Initial.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db1Migrations/MyDb1ContextModelSnapshot.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db2Migrations/20260511233305_Initial.Designer.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db2Migrations/20260511233305_Initial.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db2Migrations/MyDb2ContextModelSnapshot.cs (changed)
1 directly: Aspire.Playground.Tests

📄 playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/SqlServerEndToEnd.Common.csproj (changed)
1 directly: Aspire.Playground.Tests

🔧 src/Aspire.Hosting.EntityFrameworkCore/EFResourceBuilderExtensions.cs (changed source)
1 directly: Aspire.Hosting.EntityFrameworkCore.Tests

🧪 tests/Aspire.Hosting.EntityFrameworkCore.Tests/AddEFMigrationsTests.cs (changed test)
1 directly: Aspire.Hosting.EntityFrameworkCore.Tests

Job reasons

Job Triggered by
extension-e2e src/Aspire.Hosting.EntityFrameworkCore/EFResourceBuilderExtensions.cs
• affected project Aspire.Hosting.EntityFrameworkCore
typescript-api-compat affected project Aspire.Hosting.EntityFrameworkCore

Selection computed for commit 82bd75e.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated 1 comment.

Files not reviewed (2)
  • playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db1Migrations/20260511233127_Initial.Designer.cs: Generated file
  • playground/SqlServerEndToEnd/SqlServerEndToEnd.Common/Db2Migrations/20260511233305_Initial.Designer.cs: Generated file

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@radical Ankit Jain (radical) added the area-integrations Issues pertaining to Aspire Integrations packages label Jun 25, 2026

@mitchdenny Mitch Denny (mitchdenny) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

@mitchdenny
Mitch Denny (mitchdenny) merged commit 36b8a7b into main Jul 14, 2026
661 of 664 checks passed
@mitchdenny
Mitch Denny (mitchdenny) deleted the copilot/fix-db1-migrations-start-issue branch July 14, 2026 01:37
@microsoft-github-policy-service microsoft-github-policy-service Bot added this to the 13.5 milestone Jul 14, 2026
@aspire-repo-bot

Copy link
Copy Markdown
Contributor

✅ No documentation update needed.

Step 5 branch taken: docs_optional → bug_fix_restores_documented_behavior

Triggered signals: none (signal_count = 0)

Rationale: PR #18452 is a bug fix that corrects AddEFMigrations(...).WithReference(<db>) failing with The ConnectionString property has not been initialized. The root cause was that AddEFMigrationCommands eagerly copied only startup-project environment annotations before .WithReference(<db>) was called, so ConnectionStrings__<db> was never forwarded to the hidden dotnet-ef tool resource.

The fix adds a lazy WithEnvironment callback that forwards the migration resource's own environment callbacks at start time. No new public API was introduced (confirmed in PR checklist). Changed files:

  • src/Aspire.Hosting.EntityFrameworkCore/EFResourceBuilderExtensions.cs — bug fix (17 additions, lazy env forwarding)
  • tests/Aspire.Hosting.EntityFrameworkCore.Tests/AddEFMigrationsTests.cs — test for the fix
  • playground/SqlServerEndToEnd/** — playground updates (6 files, mostly 1-line changes)

The .WithReference() pattern is an existing documented feature; this fix restores the implementation to match the already-documented expected behavior. No docs update is required.

@github-actions github-actions Bot locked and limited conversation to collaborators Aug 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-integrations Issues pertaining to Aspire Integrations packages entityframework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

db1-migrations in SQL Playground fails to start

5 participants