Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d2f7054

Browse files
committed
Fix relationship cycle breaking logic in CSharpRuntimeModelCodeGenerator.
Don't allocate Queue unless necessary. Fix an issue with configuration of an FK to the base type. Part of #32422
1 parent a376787 commit d2f7054

File tree

12 files changed

+1122
-132
lines changed

12 files changed

+1122
-132
lines changed

src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -998,53 +998,10 @@ private void Create(
998998
private static Type? GetValueConverterType(IProperty property)
999999
{
10001000
var annotation = property.FindAnnotation(CoreAnnotationNames.ValueConverterType);
1001-
if (annotation != null)
1002-
{
1003-
return (Type?)annotation.Value;
1004-
}
1005-
1006-
var principalProperty = property;
1007-
var i = 0;
1008-
for (; i < ForeignKey.LongestFkChainAllowedLength; i++)
1009-
{
1010-
IProperty? nextProperty = null;
1011-
foreach (var foreignKey in principalProperty.GetContainingForeignKeys())
1012-
{
1013-
for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
1014-
{
1015-
if (principalProperty == foreignKey.Properties[propertyIndex])
1016-
{
1017-
var newPrincipalProperty = foreignKey.PrincipalKey.Properties[propertyIndex];
1018-
if (newPrincipalProperty == property
1019-
|| newPrincipalProperty == principalProperty)
1020-
{
1021-
break;
1022-
}
1023-
1024-
annotation = newPrincipalProperty.FindAnnotation(CoreAnnotationNames.ValueConverterType);
1025-
if (annotation != null)
1026-
{
1027-
return (Type?)annotation.Value;
1028-
}
1029-
1030-
nextProperty = newPrincipalProperty;
1031-
}
1032-
}
1033-
}
1034-
1035-
if (nextProperty == null)
1036-
{
1037-
break;
1038-
}
1039-
1040-
principalProperty = nextProperty;
1041-
}
1042-
1043-
return i == ForeignKey.LongestFkChainAllowedLength
1044-
? throw new InvalidOperationException(
1045-
CoreStrings.RelationshipCycle(
1046-
property.DeclaringType.DisplayName(), property.Name, "ValueConverterType"))
1047-
: null;
1001+
return annotation != null
1002+
? (Type?)annotation.Value
1003+
: ((Property)property).GetConversion(throwOnProviderClrTypeConflict: false, throwOnValueConverterConflict: false)
1004+
.ValueConverterType;
10481005
}
10491006

10501007
private void PropertyBaseParameters(

src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,7 +3800,7 @@ private static bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignK
38003800
{
38013801
using var batch = ModelBuilder.Metadata.DelayConventions();
38023802
var foreignKey = SetOrAddForeignKey(
3803-
foreignKey: null, principalEntityTypeBuilder, dependentProperties, principalKey,
3803+
foreignKey: null, principalEntityTypeBuilder, this, dependentProperties, principalKey,
38043804
propertyBaseName, required, configurationSource)!;
38053805

38063806
if (foreignKey == null)
@@ -3833,15 +3833,22 @@ private static bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignK
38333833
{
38343834
using var batch = ModelBuilder.Metadata.DelayConventions();
38353835
var updatedForeignKey = SetOrAddForeignKey(
3836-
foreignKey, foreignKey.PrincipalEntityType.Builder, dependentProperties, principalKey,
3837-
propertyBaseName, isRequired, configurationSource)!;
3836+
foreignKey,
3837+
foreignKey.PrincipalEntityType.Builder,
3838+
foreignKey.DeclaringEntityType.Builder,
3839+
dependentProperties,
3840+
principalKey,
3841+
propertyBaseName,
3842+
isRequired,
3843+
configurationSource)!;
38383844

38393845
return (InternalForeignKeyBuilder?)batch.Run(updatedForeignKey)?.Builder;
38403846
}
38413847

38423848
private ForeignKey? SetOrAddForeignKey(
38433849
ForeignKey? foreignKey,
38443850
InternalEntityTypeBuilder principalEntityTypeBuilder,
3851+
InternalEntityTypeBuilder dependentEntityTypeBuilder,
38453852
IReadOnlyList<Property>? dependentProperties,
38463853
Key? principalKey,
38473854
string? propertyBaseName,
@@ -3889,7 +3896,8 @@ private static bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignK
38893896

38903897
if (dependentProperties != null)
38913898
{
3892-
dependentProperties = GetActualProperties(dependentProperties, ConfigurationSource.Convention)!;
3899+
dependentProperties = dependentEntityTypeBuilder.GetActualProperties(dependentProperties, ConfigurationSource.Convention)!;
3900+
38933901
if (principalKey == null)
38943902
{
38953903
var principalKeyProperties = principalBaseEntityTypeBuilder.TryCreateUniqueProperties(

src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3194,6 +3194,18 @@ private static InternalForeignKeyBuilder MergeFacetsFrom(Navigation newNavigatio
31943194
.Select(r => r.Builder));
31953195
foreach (var candidateRelationship in candidates)
31963196
{
3197+
var candidateFk = candidateRelationship.Metadata;
3198+
if (principalEndConfigurationSource.OverridesStrictly(
3199+
candidateFk.GetDependentToPrincipalConfigurationSource())
3200+
&& (principalEntityType != candidateFk.PrincipalEntityType
3201+
|| dependentEntityType != candidateFk.DeclaringEntityType)
3202+
&& (principalEntityType.IsAssignableFrom(dependentEntityType)
3203+
|| dependentEntityType.IsAssignableFrom(principalEntityType)))
3204+
{
3205+
// Favor the intra-hierarchical relationship with higher configuration source
3206+
continue;
3207+
}
3208+
31973209
if (!candidateRelationship.CanSetRelatedTypes(
31983210
principalEntityType,
31993211
dependentEntityType,
@@ -3216,26 +3228,26 @@ private static InternalForeignKeyBuilder MergeFacetsFrom(Navigation newNavigatio
32163228
if (configurationSource != ConfigurationSource.Explicit
32173229
&& (shouldResetToPrincipal || shouldResetToDependent)
32183230
&& (navigationToPrincipal?.Name is null || navigationToDependent?.Name is null)
3219-
&& candidateRelationship.Metadata is { DependentToPrincipal: not null, PrincipalToDependent: not null }
3231+
&& candidateFk is { DependentToPrincipal: not null, PrincipalToDependent: not null }
32203232
&& ((!candidateRelationshipInverted
3221-
&& principalEntityType.IsAssignableFrom(candidateRelationship.Metadata.PrincipalEntityType)
3222-
&& dependentEntityType.IsAssignableFrom(candidateRelationship.Metadata.DeclaringEntityType))
3233+
&& principalEntityType.IsAssignableFrom(candidateFk.PrincipalEntityType)
3234+
&& dependentEntityType.IsAssignableFrom(candidateFk.DeclaringEntityType))
32233235
|| (candidateRelationshipInverted
3224-
&& principalEntityType.IsAssignableFrom(candidateRelationship.Metadata.DeclaringEntityType)
3225-
&& dependentEntityType.IsAssignableFrom(candidateRelationship.Metadata.PrincipalEntityType))))
3236+
&& principalEntityType.IsAssignableFrom(candidateFk.DeclaringEntityType)
3237+
&& dependentEntityType.IsAssignableFrom(candidateFk.PrincipalEntityType))))
32263238
{
32273239
// Favor derived bi-directional relationships over one-directional on base
32283240
continue;
32293241
}
32303242

32313243
if (dependentProperties != null
3232-
&& !Property.AreCompatible(dependentProperties, candidateRelationship.Metadata.DeclaringEntityType))
3244+
&& !Property.AreCompatible(dependentProperties, candidateFk.DeclaringEntityType))
32333245
{
32343246
continue;
32353247
}
32363248

32373249
if (principalProperties != null
3238-
&& !Property.AreCompatible(principalProperties, candidateRelationship.Metadata.PrincipalEntityType))
3250+
&& !Property.AreCompatible(principalProperties, candidateFk.PrincipalEntityType))
32393251
{
32403252
continue;
32413253
}

src/EFCore/Metadata/Internal/InternalTypeBaseBuilder.cs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -642,19 +642,39 @@ public virtual (bool, IReadOnlyList<Property>?) TryCreateUniqueProperties(
642642
return null;
643643
}
644644

645+
if (properties.Count == 0)
646+
{
647+
return properties;
648+
}
649+
650+
for (var i = 0; ; i++)
651+
{
652+
var property = properties[i];
653+
if (!property.IsInModel || !property.DeclaringType.IsAssignableFrom(Metadata))
654+
{
655+
break;
656+
}
657+
658+
if (i == properties.Count - 1)
659+
{
660+
return properties;
661+
}
662+
}
663+
645664
var actualProperties = new Property[properties.Count];
646665
for (var i = 0; i < actualProperties.Length; i++)
647666
{
648667
var property = properties[i];
649668
var typeConfigurationSource = property.GetTypeConfigurationSource();
650-
var builder = property.IsInModel && property.DeclaringType.IsAssignableFrom(Metadata)
651-
? property.Builder
652-
: Property(
653-
typeConfigurationSource.Overrides(ConfigurationSource.DataAnnotation) ? property.ClrType : null,
654-
property.Name,
655-
property.GetIdentifyingMemberInfo(),
656-
typeConfigurationSource.Overrides(ConfigurationSource.DataAnnotation) ? typeConfigurationSource : null,
657-
configurationSource);
669+
var builder = Property(
670+
typeConfigurationSource.Overrides(ConfigurationSource.DataAnnotation)
671+
|| (property.IsInModel && Metadata.IsAssignableFrom(property.DeclaringType))
672+
? property.ClrType
673+
: null,
674+
property.Name,
675+
property.GetIdentifyingMemberInfo(),
676+
typeConfigurationSource.Overrides(ConfigurationSource.DataAnnotation) ? typeConfigurationSource : null,
677+
configurationSource);
658678

659679
if (builder == null)
660680
{

0 commit comments

Comments
 (0)