Skip to content

Commit

Permalink
Break up KeyDiscoveryConvention
Browse files Browse the repository at this point in the history
Derive JsonTypesTestBase from NonSharedModelTestBase

Part of #28866
  • Loading branch information
AndriySvyryd committed Dec 20, 2023
1 parent 8e4dc09 commit 0679cf3
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,7 @@ protected override void ProcessKeyProperties(IList<IConventionProperty> keyPrope
keyProperties.Add(partitionKeyProperty);
}
}

base.ProcessKeyProperties(keyProperties, entityType);
}
}
76 changes: 50 additions & 26 deletions src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
/// is configured using the foreign key properties with an extra property that matches the naming convention above.
/// </para>
/// <para>
/// If the entity type is a many-to-many join entity type then the many-to-many foreign key properties are used.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-conventions">Model building conventions</see> for more information and examples.
/// </para>
/// </remarks>
Expand Down Expand Up @@ -57,17 +60,43 @@ public KeyDiscoveryConvention(ProviderConventionSetBuilderDependencies dependenc
protected virtual void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entityTypeBuilder)
{
var entityType = entityTypeBuilder.Metadata;
if (entityType.BaseType != null
|| (entityType.IsKeyless && entityType.GetIsKeylessConfigurationSource() != ConfigurationSource.Convention)
|| !entityTypeBuilder.CanSetPrimaryKey((IReadOnlyList<IConventionProperty>?)null))
if (!ShouldDiscoverKeyProperties(entityType))
{
return;
}

var keyProperties = DiscoverKeyProperties(entityType);
if (keyProperties != null)
{
ProcessKeyProperties(keyProperties, entityType);

if (keyProperties.Count > 0)
{
entityTypeBuilder.PrimaryKey(keyProperties);
}
}
}

/// <summary>
/// Determines whether key properties should be discovered for the entity type.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns><see langword="true"/> if key properties should be discovered, otherwise <see langword="false"/>.</returns>
protected virtual bool ShouldDiscoverKeyProperties(IConventionEntityType entityType) =>
entityType.BaseType == null
&& (!entityType.IsKeyless || entityType.GetIsKeylessConfigurationSource() == ConfigurationSource.Convention)
&& entityType.Builder.CanSetPrimaryKey((IReadOnlyList<IConventionProperty>?)null);

/// <summary>
/// Returns the properties that should be used for the primary key.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns>The properties that should be used for the primary key.</returns>
protected virtual List<IConventionProperty>? DiscoverKeyProperties(IConventionEntityType entityType)
{
List<IConventionProperty>? keyProperties = null;
var ownership = entityType.FindOwnership();
if (ownership != null
&& ownership.DeclaringEntityType != entityType)
if (ownership?.DeclaringEntityType != entityType)
{
ownership = null;
}
Expand All @@ -86,7 +115,7 @@ protected virtual void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entit
if (keyProperties.Count > 1)
{
Dependencies.Logger.MultiplePrimaryKeyCandidates(keyProperties[0], keyProperties[1]);
return;
return null;
}
}

Expand All @@ -101,7 +130,7 @@ protected virtual void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entit
|| primaryKey!.Properties.Count == 1
|| ownership.Properties.Contains(shadowProperty))
{
shadowProperty = entityTypeBuilder.CreateUniqueProperty(typeof(int), "Id", required: true)!.Metadata;
shadowProperty = entityType.Builder.CreateUniqueProperty(typeof(int), "Id", required: true)!.Metadata;
}

keyProperties.Clear();
Expand All @@ -125,6 +154,19 @@ protected virtual void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entit
}
}

return keyProperties;
}

/// <summary>
/// Adds or removes properties to be used for the primary key.
/// </summary>
/// <param name="keyProperties">The properties that will be used to configure the key.</param>
/// <param name="entityType">The entity type being configured.</param>
protected virtual void ProcessKeyProperties(
IList<IConventionProperty> keyProperties,
IConventionEntityType entityType)
{
// Remove duplicates
for (var i = keyProperties.Count - 1; i >= 0; i--)
{
var property = keyProperties[i];
Expand All @@ -137,24 +179,6 @@ protected virtual void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entit
}
}
}

ProcessKeyProperties(keyProperties, entityType);

if (keyProperties.Count > 0)
{
entityTypeBuilder.PrimaryKey(keyProperties);
}
}

/// <summary>
/// Adds or removes properties to be used for the primary key.
/// </summary>
/// <param name="keyProperties">The properties that will be used to configure the key.</param>
/// <param name="entityType">The entity type being configured.</param>
protected virtual void ProcessKeyProperties(
IList<IConventionProperty> keyProperties,
IConventionEntityType entityType)
{
}

/// <summary>
Expand All @@ -179,9 +203,9 @@ public static IEnumerable<IConventionProperty> DiscoverKeyProperties(
&& p.Name.StartsWith(entityTypeName, StringComparison.OrdinalIgnoreCase)
&& p.Name.EndsWith(KeySuffix, StringComparison.OrdinalIgnoreCase));
}
// ReSharper restore PossibleMultipleEnumeration

return keyProperties;
// ReSharper restore PossibleMultipleEnumeration
}

/// <summary>
Expand Down
Loading

0 comments on commit 0679cf3

Please sign in to comment.