Skip to content

Allow excluding foreign key from migrations#37815

Open
roji wants to merge 1 commit intodotnet:mainfrom
roji:NoMoreFks
Open

Allow excluding foreign key from migrations#37815
roji wants to merge 1 commit intodotnet:mainfrom
roji:NoMoreFks

Conversation

@roji
Copy link
Member

@roji roji commented Feb 28, 2026

Closes #15854

@roji roji marked this pull request as ready for review February 28, 2026 17:18
@roji roji requested a review from a team as a code owner February 28, 2026 17:18
Copilot AI review requested due to automatic review settings February 28, 2026 17:18
Copy link

Copilot AI left a comment

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 introduces a relational model annotation and fluent API to allow foreign key constraints to exist in the EF model while being excluded from migrations (i.e., migrations won’t create/drop the DB constraint), closing #15854.

Changes:

  • Add ExcludeFromMigrations() on relationship builders and persist it via a new relational FK annotation.
  • Update migrations diffing to skip add/drop FK operations when a foreign key constraint is excluded.
  • Add design-time and functional test coverage (snapshot/codegen + provider SQL baselines) for the new behavior.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsSqliteTest.cs Adds provider SQL assertion for excluded-FK migration (index only).
test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs Adds provider SQL assertion for excluded-FK migration (index only).
test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs Adds model differ tests validating operations when FK constraints are excluded.
test/EFCore.Relational.Tests/Extensions/RelationalMetadataExtensionsTest.cs Verifies get/set behavior for the new excluded-from-migrations FK metadata.
test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs Verifies fluent API surface and configuration-source behavior for FK exclusion.
test/EFCore.Relational.Tests/Design/AnnotationCodeGeneratorTest.cs Ensures snapshot codegen emits ExcludeFromMigrations fluent API for FKs.
test/EFCore.Relational.Specification.Tests/Migrations/MigrationsTestBase.cs Adds cross-provider scenario ensuring DB FK constraints aren’t created.
test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs Updates “new annotations” guard lists for the new relational annotation name.
test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs Adds snapshot roundtrip test verifying FK exclusion is stored in snapshots.
src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs Skips FK add/drop operations when FK constraints are excluded from migrations.
src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs Introduces IsForeignKeyExcludedFromMigrations annotation name and registers it.
src/EFCore.Relational/Metadata/Internal/ForeignKeyConstraint.cs Surfaces FK exclusion at the constraint level for migrations diffing.
src/EFCore.Relational/Metadata/IForeignKeyConstraint.cs Adds IsExcludedFromMigrations to the public constraint metadata interface.
src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs Removes the new annotation from runtime annotations.
src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs Adds metadata accessors for FK exclusion + configuration source helpers.
src/EFCore.Relational/Extensions/RelationalForeignKeyBuilderExtensions.cs Adds ExcludeFromMigrations fluent APIs for relationship builders.
src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs Removes the new annotation from runtime codegen output.
src/EFCore.Relational/Design/AnnotationCodeGenerator.cs Generates fluent API calls for FK exclusion in snapshots.

/// <param name="referenceCollectionBuilder">The builder being used to configure the relationship.</param>
/// <param name="excluded">A value indicating whether the foreign key constraint is excluded from migrations.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ReferenceCollectionBuilder ExcludeFromMigrations(
Copy link
Member Author

Choose a reason for hiding this comment

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

@AndriySvyryd see suggestion to rename this to ExcludeForeignKeyFromMigrations, to make it clear what's being excluded.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good

if (runtime)
{
annotations.Remove(RelationalAnnotationNames.ForeignKeyMappings);
annotations.Remove(RelationalAnnotationNames.IsForeignKeyExcludedFromMigrations);
Copy link
Member

Choose a reason for hiding this comment

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

This is not a runtime annotation.
Modify a test in CompiledModelRelationalTestBase to verify this

Assert.Equal("IX_Amoeba_ParentId", createIndexOperation.Name);
Assert.Equal(new[] { "ParentId" }, createIndexOperation.Columns);
});

Copy link
Member

Choose a reason for hiding this comment

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

Also add a test that excludes an existing FK without removing or changing it and a test that excludes an existing FK and changes OnDelete on it

Assert.Equal("LemonSupreme", foreignKey.GetConstraintName());
}

[ConditionalFact]
Copy link
Member

Choose a reason for hiding this comment

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

Move these tests to RelationalModelBuilderTest, add tests for owned and many-to-many

@AndriySvyryd AndriySvyryd assigned roji and unassigned AndriySvyryd Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow FKs to exist in the model but avoid creating them in the database

3 participants