Skip to content

Commit

Permalink
Use OrderedDictionary or Dictionary instead of SortedDictionary in Ru…
Browse files Browse the repository at this point in the history
…ntimeModel (#32124)

Fixes #31142
Fixes #19361
  • Loading branch information
AndriySvyryd authored Oct 24, 2023
1 parent 00d51eb commit d8e9f61
Show file tree
Hide file tree
Showing 46 changed files with 2,662 additions and 440 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ public virtual void BuildModel_AdventureWorks()
AdventureWorksContextBase.ConfigureModel(builder);

// ReSharper disable once UnusedVariable
var model = builder.Model;
var model = builder.FinalizeModel();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ private static void UpdateSequences(IReadOnlyModel model, string version)
.Select(a => new Sequence(model, a.Name));
#pragma warning restore CS0618 // Type or member is obsolete

var sequencesDictionary = new SortedDictionary<(string, string?), ISequence>();
var sequencesDictionary = new Dictionary<(string, string?), ISequence>();
foreach (var sequence in sequences)
{
sequencesDictionary[(sequence.Name, sequence.ModelSchema)] = sequence;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,11 @@ void RunInitialization()
}
}
model.Customize();
_instance = model;
}")
model.Customize();")
.Append(" _instance = (")
.Append(className)
.AppendLine(")model.FinalizeModel();")
.AppendLine("}")
.AppendLine()
.Append("private static ").Append(className).AppendLine(" _instance;")
.AppendLine("public static IModel Instance => _instance;")
Expand Down Expand Up @@ -225,6 +227,32 @@ private string CreateModelBuilder(

using (mainBuilder.Indent())
{
AddNamespace(typeof(Guid), namespaces);
mainBuilder
.AppendLine($"private {className}()")
.IncrementIndent()
.Append(": base(skipDetectChanges: ")
.Append(_code.Literal(((IRuntimeModel)model).SkipDetectChanges))
.Append(", modelId: ")
.Append(_code.Literal(model.ModelId))
.Append(", entityTypeCount: ")
.Append(_code.Literal(model.GetEntityTypes().Count()));

var typeConfigurationCount = model.GetTypeMappingConfigurations().Count();
if (typeConfigurationCount > 0)
{
mainBuilder
.Append(", typeConfigurationCount: ")
.Append(_code.Literal(typeConfigurationCount));
}

mainBuilder
.AppendLine(")")
.DecrementIndent()
.AppendLine("{")
.AppendLine("}")
.AppendLine();

mainBuilder
.AppendLine("partial void Initialize()")
.AppendLine("{");
Expand Down Expand Up @@ -692,6 +720,82 @@ private void Create(IEntityType entityType, CSharpRuntimeAnnotationCodeGenerator
.Append(_code.UnknownLiteral(discriminatorValue));
}

var derivedTypesCount = entityType.GetDirectlyDerivedTypes().Count();
if (derivedTypesCount != 0)
{
mainBuilder.AppendLine(",")
.Append("derivedTypesCount: ")
.Append(_code.Literal(derivedTypesCount));
}

mainBuilder.AppendLine(",")
.Append("propertyCount: ")
.Append(_code.Literal(entityType.GetDeclaredProperties().Count()));

var complexPropertyCount = entityType.GetDeclaredComplexProperties().Count();
if (complexPropertyCount != 0)
{
mainBuilder.AppendLine(",")
.Append("complexPropertyCount: ")
.Append(_code.Literal(complexPropertyCount));
}

var navigationCount = entityType.GetDeclaredNavigations().Count();
if (navigationCount != 0)
{
mainBuilder.AppendLine(",")
.Append("navigationCount: ")
.Append(_code.Literal(navigationCount));
}

var skipNavigationCount = entityType.GetDeclaredSkipNavigations().Count();
if (skipNavigationCount != 0)
{
mainBuilder.AppendLine(",")
.Append("skipNavigationCount: ")
.Append(_code.Literal(skipNavigationCount));
}

var servicePropertyCount = entityType.GetDeclaredServiceProperties().Count();
if (servicePropertyCount != 0)
{
mainBuilder.AppendLine(",")
.Append("servicePropertyCount: ")
.Append(_code.Literal(servicePropertyCount));
}

var foreignKeyCount = entityType.GetDeclaredForeignKeys().Count();
if (foreignKeyCount != 0)
{
mainBuilder.AppendLine(",")
.Append("foreignKeyCount: ")
.Append(_code.Literal(foreignKeyCount));
}

var unnamedIndexCount = entityType.GetDeclaredIndexes().Count(i => i.Name == null);
if (unnamedIndexCount != 0)
{
mainBuilder.AppendLine(",")
.Append("unnamedIndexCount: ")
.Append(_code.Literal(unnamedIndexCount));
}

var namedIndexCount = entityType.GetDeclaredIndexes().Count(i => i.Name != null);
if (namedIndexCount != 0)
{
mainBuilder.AppendLine(",")
.Append("namedIndexCount: ")
.Append(_code.Literal(namedIndexCount));
}

var keyCount = entityType.GetDeclaredKeys().Count();
if (keyCount != 0)
{
mainBuilder.AppendLine(",")
.Append("keyCount: ")
.Append(_code.Literal(keyCount));
}

mainBuilder
.AppendLine(");")
.AppendLine()
Expand Down Expand Up @@ -1264,6 +1368,18 @@ private void CreateComplexProperty(
.Append(_code.Literal(true));
}

mainBuilder.AppendLine(",")
.Append("propertyCount: ")
.Append(_code.Literal(complexType.GetDeclaredProperties().Count()));

var complexPropertyCount = complexType.GetDeclaredComplexProperties().Count();
if (complexPropertyCount != 0)
{
mainBuilder.AppendLine(",")
.Append("complexPropertyCount: ")
.Append(_code.Literal(complexPropertyCount));
}

mainBuilder
.AppendLine(");")
.AppendLine()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ public override void Generate(IModel model, CSharpRuntimeAnnotationCodeGenerator

if (annotations.TryGetAndRemove(
RelationalAnnotationNames.DbFunctions,
out SortedDictionary<string, IDbFunction> functions))
out IReadOnlyDictionary<string, IDbFunction> functions))
{
parameters.Namespaces.Add(typeof(SortedDictionary<,>).Namespace!);
parameters.Namespaces.Add(typeof(Dictionary<,>).Namespace!);
parameters.Namespaces.Add(typeof(BindingFlags).Namespace!);
var functionsVariable = Dependencies.CSharpHelper.Identifier("functions", parameters.ScopeVariables, capitalize: false);
parameters.MainBuilder
.Append("var ").Append(functionsVariable).AppendLine(" = new SortedDictionary<string, IDbFunction>();");
.Append("var ").Append(functionsVariable).AppendLine(" = new Dictionary<string, IDbFunction>();");

foreach (var function in functions.Values)
foreach (var function in functions.OrderBy(t => t.Key).Select(t => t.Value))
{
Create(function, functionsVariable, parameters);
}
Expand All @@ -84,12 +84,12 @@ public override void Generate(IModel model, CSharpRuntimeAnnotationCodeGenerator

if (annotations.TryGetAndRemove(
RelationalAnnotationNames.Sequences,
out SortedDictionary<(string, string?), ISequence> sequences))
out IReadOnlyDictionary<(string, string?), ISequence> sequences))
{
parameters.Namespaces.Add(typeof(SortedDictionary<,>).Namespace!);
parameters.Namespaces.Add(typeof(Dictionary<,>).Namespace!);
var sequencesVariable = Dependencies.CSharpHelper.Identifier("sequences", parameters.ScopeVariables, capitalize: false);
var mainBuilder = parameters.MainBuilder;
mainBuilder.Append("var ").Append(sequencesVariable).Append(" = new SortedDictionary<(string, string");
mainBuilder.Append("var ").Append(sequencesVariable).Append(" = new Dictionary<(string, string");

if (parameters.UseNullableReferenceTypes)
{
Expand All @@ -98,9 +98,9 @@ public override void Generate(IModel model, CSharpRuntimeAnnotationCodeGenerator

mainBuilder.AppendLine("), ISequence>();");

foreach (var sequencePair in sequences)
foreach (var sequence in sequences.OrderBy(t => t.Key).Select(t => t.Value))
{
Create(sequencePair.Value, sequencesVariable, parameters);
Create(sequence, sequencesVariable, parameters);
}

GenerateSimpleAnnotation(RelationalAnnotationNames.Sequences, sequencesVariable, parameters);
Expand Down
4 changes: 2 additions & 2 deletions src/EFCore.Relational/Extensions/RelationalModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public static IEnumerable<IReadOnlySequence> GetSequences(this IReadOnlyModel mo
/// <param name="method">The <see cref="MethodInfo" /> for the method that is mapped to the function.</param>
/// <returns>The function or <see langword="null" /> if the method is not mapped.</returns>
public static IDbFunction? FindDbFunction(this IModel model, MethodInfo method)
=> (IDbFunction?)((IReadOnlyModel)model).FindDbFunction(method);
=> DbFunction.FindDbFunction(model, method);

/// <summary>
/// Finds a function that is mapped to the method represented by the given name.
Expand Down Expand Up @@ -349,7 +349,7 @@ public static IEnumerable<IReadOnlySequence> GetSequences(this IReadOnlyModel mo
/// <param name="name">The model name of the function.</param>
/// <returns>The function or <see langword="null" /> if the method is not mapped.</returns>
public static IDbFunction? FindDbFunction(this IModel model, string name)
=> (IDbFunction?)((IReadOnlyModel)model).FindDbFunction(name);
=> DbFunction.FindDbFunction(model, name);

/// <summary>
/// Creates an <see cref="IMutableDbFunction" /> mapped to the given method.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ protected override void ProcessModelAnnotations(

if (annotations.TryGetValue(RelationalAnnotationNames.DbFunctions, out var functions))
{
var runtimeFunctions = new SortedDictionary<string, IDbFunction>(StringComparer.Ordinal);
foreach (var (key, dbFunction) in (SortedDictionary<string, IDbFunction>)functions!)
var runtimeFunctions = new Dictionary<string, IDbFunction>(StringComparer.Ordinal);
foreach (var (key, dbFunction) in (Dictionary<string, IDbFunction>)functions!)
{
var runtimeFunction = Create(dbFunction, runtimeModel);
runtimeFunctions[key] = runtimeFunction;
Expand All @@ -87,8 +87,8 @@ protected override void ProcessModelAnnotations(

if (annotations.TryGetValue(RelationalAnnotationNames.Sequences, out var sequences))
{
var runtimeSequences = new SortedDictionary<(string, string?), ISequence>();
foreach (var (key, value) in (SortedDictionary<(string, string?), ISequence>)sequences!)
var runtimeSequences = new Dictionary<(string, string?), ISequence>();
foreach (var (key, value) in (Dictionary<(string, string?), ISequence>)sequences!)
{
var runtimeSequence = Create(value, runtimeModel);
runtimeSequences[key] = runtimeSequence;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,13 @@ public virtual void ProcessModelFinalizing(
IConventionContext<IConventionModelBuilder> context)
{
var model = modelBuilder.Metadata;
var modelSequences =
(SortedDictionary<(string Name, string? Schema), ISequence>?)model[RelationalAnnotationNames.Sequences];

var modelSequences =
(IReadOnlyDictionary<(string Name, string? Schema), ISequence>?)model[RelationalAnnotationNames.Sequences];
if (modelSequences != null)
{
var maxLength = model.GetMaxIdentifierLength();
var toReplace = modelSequences
.Where(s => s.Key.Name.Length > maxLength).ToList();
.Where(s => s.Key.Name.Length > maxLength).OrderBy(s => s.Key).ToList();

foreach (var ((name, schema), sequence) in toReplace)
{
Expand Down
22 changes: 11 additions & 11 deletions src/EFCore.Relational/Metadata/Internal/DbFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ public override bool IsReadOnly
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public static IEnumerable<IDbFunction> GetDbFunctions(IReadOnlyModel model)
=> ((SortedDictionary<string, IDbFunction>?)model[RelationalAnnotationNames.DbFunctions])
?.Values
=> ((Dictionary<string, IDbFunction>?)model[RelationalAnnotationNames.DbFunctions])
?.OrderBy(t => t.Key).Select(t => t.Value)
?? Enumerable.Empty<IDbFunction>();

/// <summary>
Expand All @@ -203,8 +203,8 @@ public static IEnumerable<IDbFunction> GetDbFunctions(IReadOnlyModel model)
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public static IReadOnlyDbFunction? FindDbFunction(IReadOnlyModel model, MethodInfo methodInfo)
=> model[RelationalAnnotationNames.DbFunctions] is SortedDictionary<string, IDbFunction> functions
public static IDbFunction? FindDbFunction(IReadOnlyModel model, MethodInfo methodInfo)
=> model[RelationalAnnotationNames.DbFunctions] is Dictionary<string, IDbFunction> functions
&& functions.TryGetValue(GetFunctionName(methodInfo), out var dbFunction)
? dbFunction
: null;
Expand All @@ -215,8 +215,8 @@ public static IEnumerable<IDbFunction> GetDbFunctions(IReadOnlyModel model)
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public static IReadOnlyDbFunction? FindDbFunction(IReadOnlyModel model, string name)
=> model[RelationalAnnotationNames.DbFunctions] is SortedDictionary<string, IDbFunction> functions
public static IDbFunction? FindDbFunction(IReadOnlyModel model, string name)
=> model[RelationalAnnotationNames.DbFunctions] is Dictionary<string, IDbFunction> functions
&& functions.TryGetValue(name, out var dbFunction)
? dbFunction
: null;
Expand Down Expand Up @@ -256,9 +256,9 @@ public static DbFunction AddDbFunction(
return function;
}

private static SortedDictionary<string, IDbFunction> GetOrCreateFunctions(IMutableModel model)
=> (SortedDictionary<string, IDbFunction>)(
model[RelationalAnnotationNames.DbFunctions] ??= new SortedDictionary<string, IDbFunction>(StringComparer.Ordinal));
private static Dictionary<string, IDbFunction> GetOrCreateFunctions(IMutableModel model)
=> (Dictionary<string, IDbFunction>)(
model[RelationalAnnotationNames.DbFunctions] ??= new Dictionary<string, IDbFunction>(StringComparer.Ordinal));

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -270,7 +270,7 @@ private static SortedDictionary<string, IDbFunction> GetOrCreateFunctions(IMutab
IMutableModel model,
MethodInfo methodInfo)
{
if (model[RelationalAnnotationNames.DbFunctions] is SortedDictionary<string, IDbFunction> functions)
if (model[RelationalAnnotationNames.DbFunctions] is Dictionary<string, IDbFunction> functions)
{
var name = GetFunctionName(methodInfo);
if (functions.TryGetValue(name, out var function))
Expand All @@ -296,7 +296,7 @@ private static SortedDictionary<string, IDbFunction> GetOrCreateFunctions(IMutab
IMutableModel model,
string name)
{
if (model[RelationalAnnotationNames.DbFunctions] is SortedDictionary<string, IDbFunction> functions
if (model[RelationalAnnotationNames.DbFunctions] is Dictionary<string, IDbFunction> functions
&& functions.TryGetValue(name, out var function))
{
functions.Remove(name);
Expand Down
Loading

0 comments on commit d8e9f61

Please sign in to comment.