java-topology/defects/efcore/patch/efcore-0003-fk-discovery-foreignkeyprops-hashset.patch

44 lines
2.6 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000059
diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs
index xxxxxxx..xxxxxxx 100644
--- a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs
+++ b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs
@@ -496,14 +496,17 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
foreach (var key in dependentEntityType.GetKeys())
{
var isKeyContainedInForeignKey = true;
+ // efcore-0003 fix: build a HashSet once from foreignKeyProperties so that
+ // key.Properties[i] lookup is O(1) instead of O(FK_props) per iteration.
+ // Without fix: O(keys × key_props × fk_props) model-build cost.
+ var foreignKeyPropertySet = foreignKeyProperties != null
+ ? new HashSet<IConventionProperty>(foreignKeyProperties, ReferenceEqualityComparer.Instance)
+ : null;
// ReSharper disable once LoopCanBeConvertedToQuery
// ReSharper disable once ForCanBeConvertedToForeach
for (var i = 0; i < key.Properties.Count; i++)
{
- if (!foreignKeyProperties.Contains(key.Properties[i]))
+ if (foreignKeyPropertySet == null || !foreignKeyPropertySet.Contains(key.Properties[i]))
{
isKeyContainedInForeignKey = false;
break;
}
}
@@ -742,10 +742,13 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
public virtual void ProcessKeyAdded(IConventionKeyBuilder keyBuilder, IConventionContext<IConventionKeyBuilder> context)
{
var key = keyBuilder.Metadata;
foreach (var foreignKey in key.DeclaringEntityType.GetDerivedTypesInclusive()
.SelectMany(t => t.GetDeclaredForeignKeys()).ToList())
{
- if (key.Properties.All(p => foreignKey.Properties.Contains(p))
+ // efcore-0003 fix: build HashSet once per foreignKey so key.Properties.All()
+ // is O(key_props) not O(key_props × fk_props).
+ var fkPropsSet = new HashSet<IConventionProperty>(foreignKey.Properties, ReferenceEqualityComparer.Instance);
+ if (key.Properties.All(p => fkPropsSet.Contains(p))
&& (!foreignKey.IsUnique || foreignKey.DeclaringEntityType.BaseType != null))
{
foreignKey.Builder.HasForeignKey((IReadOnlyList<IConventionProperty>?)null);
}
}
}