diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs
index 45194d0a2a1..beb97f2b1b1 100644
--- a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs
+++ b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs
@@ -50,6 +50,9 @@ public class ForeignKeyPropertyDiscoveryConvention :
IPropertyFieldChangedConvention,
IModelFinalizingConvention
{
+ private static readonly bool UseOldBehavior35110 =
+ AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35110", out var enabled) && enabled;
+
///
/// Creates a new instance of .
///
@@ -81,13 +84,17 @@ private IConventionForeignKeyBuilder ProcessForeignKey(
IConventionContext context)
{
var shouldBeRequired = true;
- foreach (var property in relationshipBuilder.Metadata.Properties)
+ if (!relationshipBuilder.Metadata.IsOwnership
+ || UseOldBehavior35110)
{
- if (property.IsNullable)
+ foreach (var property in relationshipBuilder.Metadata.Properties)
{
- shouldBeRequired = false;
- relationshipBuilder = relationshipBuilder.IsRequired(false) ?? relationshipBuilder;
- break;
+ if (property.IsNullable)
+ {
+ shouldBeRequired = false;
+ relationshipBuilder = relationshipBuilder.IsRequired(false) ?? relationshipBuilder;
+ break;
+ }
}
}
diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
index dfeeb09c785..53d96998377 100644
--- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
+++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
@@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal;
///
public class InternalEntityTypeBuilder : InternalTypeBaseBuilder, IConventionEntityTypeBuilder
{
+ private static readonly bool UseOldBehavior35110 =
+ AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35110", out var enabled) && enabled;
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -3161,17 +3164,9 @@ public static InternalIndexBuilder DetachIndex(Index indexToDetach)
&& targetEntityType.Name == existingTargetType.ClrType.DisplayName())))
{
relationship = existingNavigation.ForeignKey.Builder;
- if (existingNavigation.ForeignKey.IsOwnership)
- {
- relationship = relationship.IsOwnership(true, configurationSource)
- ?.HasNavigations(inverse, navigation, configurationSource);
-
- relationship?.Metadata.UpdateConfigurationSource(configurationSource);
- return relationship;
- }
-
Check.DebugAssert(
- !existingTargetType.IsOwned()
+ existingNavigation.ForeignKey.IsOwnership
+ || !existingTargetType.IsOwned()
|| existingNavigation.DeclaringEntityType.IsInOwnershipPath(existingTargetType)
|| (existingTargetType.IsInOwnershipPath(existingNavigation.DeclaringEntityType)
&& existingTargetType.FindOwnership()!.PrincipalEntityType != existingNavigation.DeclaringEntityType),
@@ -3181,6 +3176,11 @@ public static InternalIndexBuilder DetachIndex(Index indexToDetach)
relationship = relationship.IsOwnership(true, configurationSource)
?.HasNavigations(inverse, navigation, configurationSource);
+ if (!UseOldBehavior35110)
+ {
+ relationship = relationship?.IsRequired(true, configurationSource);
+ }
+
relationship?.Metadata.UpdateConfigurationSource(configurationSource);
return relationship;
}
diff --git a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs
index 3c00a36a40b..5ca1a781feb 100644
--- a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs
+++ b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs
@@ -9763,6 +9763,62 @@ public void Update_AK_seed_value_with_a_referencing_foreign_key()
v => Assert.Equal(4242, v));
}));
+ [ConditionalFact]
+ public void Owned_collection_with_explicit_id()
+ => Execute(
+ modelBuilder =>
+ {
+ },
+ source =>
+ {
+ source.Entity("Microsoft.EntityFrameworkCore.Migrations.Internal.Account", b =>
+ {
+ b.Property("Id");
+ b.HasKey("Id");
+ b.ToTable("account");
+ });
+
+ source.Entity("Microsoft.EntityFrameworkCore.Migrations.Internal.Account", b =>
+ {
+ b.OwnsMany("Microsoft.EntityFrameworkCore.Migrations.Internal.AccountHolder", "AccountHolders", b1 =>
+ {
+ b1.Property("Id");
+ b1.Property("account_id");
+ b1.HasKey("Id");
+ b1.HasIndex("account_id");
+ b1.ToTable("account_holder");
+ b1.WithOwner().HasForeignKey("account_id");
+ });
+ });
+ },
+ target =>
+ {
+ target.Entity(builder =>
+ {
+ builder.ToTable("account");
+ builder.HasKey("Id");
+ builder.OwnsMany(a => a.AccountHolders, navigationBuilder =>
+ {
+ navigationBuilder.ToTable("account_holder");
+ navigationBuilder.Property("Id");
+ navigationBuilder.HasKey("Id");
+ navigationBuilder.Property("account_id");
+ navigationBuilder.WithOwner().HasForeignKey("account_id");
+ });
+ });
+ },
+ Assert.Empty);
+
+ public class Account
+ {
+ public string Id { get; set; }
+ public IEnumerable AccountHolders { get; set; } = [];
+ }
+
+ public class AccountHolder
+ {
+ }
+
[ConditionalFact]
public void SeedData_with_guid_AK_and_multiple_owned_types()
=> Execute(