Skip to content

Commit

Permalink
Make a selection of comparers public
Browse files Browse the repository at this point in the history
Fixes #20387
  • Loading branch information
ajcvickers committed Apr 5, 2020
1 parent f6978f0 commit fd33e46
Show file tree
Hide file tree
Showing 39 changed files with 571 additions and 491 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.ComponentModel;
using Castle.DynamicProxy;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.ComponentModel;
using Castle.DynamicProxy;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ public int Compare(IColumnMappingBase x, IColumnMappingBase y)
return result;
}

#pragma warning disable EF1001 // Internal EF Core API usage.
result = EntityTypePathComparer.Instance.Compare(x.Property.DeclaringEntityType, y.Property.DeclaringEntityType);
#pragma warning restore EF1001 // Internal EF Core API usage.
if (result != 0)
{
return result;
Expand Down Expand Up @@ -90,9 +88,7 @@ public int GetHashCode(IColumnMappingBase obj)
var hashCode = new HashCode();
hashCode.Add(obj.Property.Name);
hashCode.Add(obj.Column.Name);
#pragma warning disable EF1001 // Internal EF Core API usage.
hashCode.Add(obj.Property.DeclaringEntityType, EntityTypePathComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.
hashCode.Add(obj.Column.Table.Name);
hashCode.Add(obj.Column.Table.Schema);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ public ForeignKeyConstraint(
/// 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>
#pragma warning disable EF1001 // Internal EF Core API usage.
public virtual SortedSet<IForeignKey> MappedForeignKeys { get; } = new SortedSet<IForeignKey>(ForeignKeyComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
8 changes: 0 additions & 8 deletions src/EFCore.Relational/Metadata/Internal/RelationalModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -486,26 +486,20 @@ private static void PopulateInternalForeignKeys(TableBase table)
{
if (internalForeignKeys == null)
{
#pragma warning disable EF1001 // Internal EF Core API usage.
internalForeignKeys = new SortedSet<IForeignKey>(ForeignKeyComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.
}
internalForeignKeys.Add(foreignKey);

if (referencingInternalForeignKeyMap == null)
{
referencingInternalForeignKeyMap =
#pragma warning disable EF1001 // Internal EF Core API usage.
new SortedDictionary<IEntityType, IEnumerable<IForeignKey>>(EntityTypePathComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.
}

var principalEntityType = foreignKey.PrincipalEntityType;
if (!referencingInternalForeignKeyMap.TryGetValue(principalEntityType, out var internalReferencingForeignKeys))
{
#pragma warning disable EF1001 // Internal EF Core API usage.
internalReferencingForeignKeys = new SortedSet<IForeignKey>(ForeignKeyComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.
referencingInternalForeignKeyMap[principalEntityType] = internalReferencingForeignKeys;
}
((SortedSet<IForeignKey>)internalReferencingForeignKeys).Add(foreignKey);
Expand All @@ -517,9 +511,7 @@ private static void PopulateInternalForeignKeys(TableBase table)
if (internalForeignKeyMap == null)
{
internalForeignKeyMap =
#pragma warning disable EF1001 // Internal EF Core API usage.
new SortedDictionary<IEntityType, IEnumerable<IForeignKey>>(EntityTypePathComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.
table.InternalForeignKeys = internalForeignKeyMap;
}

Expand Down
2 changes: 0 additions & 2 deletions src/EFCore.Relational/Metadata/Internal/TableIndex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ public TableIndex(
/// 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>
#pragma warning disable EF1001 // Internal EF Core API usage.
public virtual SortedSet<IIndex> MappedIndexes { get; } = new SortedSet<IIndex>(IndexComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ private TableMappingBaseComparer()
/// </summary>
public int Compare(ITableMappingBase x, ITableMappingBase y)
{
#pragma warning disable EF1001 // Internal EF Core API usage.
var result = EntityTypePathComparer.Instance.Compare(x.EntityType, y.EntityType);
#pragma warning restore EF1001 // Internal EF Core API usage.
if (result != 0)
{
return result;
Expand Down Expand Up @@ -97,9 +95,7 @@ public bool Equals(ITableMappingBase x, ITableMappingBase y)
public int GetHashCode(ITableMappingBase obj)
{
var hashCode = new HashCode();
#pragma warning disable EF1001 // Internal EF Core API usage.
hashCode.Add(obj.EntityType, EntityTypePathComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.
hashCode.Add(obj.Table.Name);
hashCode.Add(obj.Table.Schema);
foreach (var columnMapping in obj.ColumnMappings)
Expand Down
2 changes: 0 additions & 2 deletions src/EFCore.Relational/Metadata/Internal/UniqueConstraint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ public UniqueConstraint(
/// 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>
#pragma warning disable EF1001 // Internal EF Core API usage.
public virtual SortedSet<IKey> MappedKeys { get; } = new SortedSet<IKey>(KeyComparer.Instance);
#pragma warning restore EF1001 // Internal EF Core API usage.

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Data.Common;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Internal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Utilities;

Expand Down
66 changes: 66 additions & 0 deletions src/EFCore/ChangeTracking/EntryCurrentValueComparer`.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Update;

namespace Microsoft.EntityFrameworkCore.ChangeTracking
{
/// <summary>
/// <para>
/// An implementation of <see cref="IComparer{T}" /> and <see cref="IEqualityComparer{T}" /> to compare current values
/// contained in <see cref="IUpdateEntry" /> internal tracking entities.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
public sealed class EntryCurrentValueComparer<TProperty> : IComparer<IUpdateEntry>, IEqualityComparer<IUpdateEntry>
{
private readonly IPropertyBase _property;
private readonly IComparer<TProperty> _underlyingComparer;

/// <summary>
/// Creates a new <see cref="EntryCurrentValueComparer" /> instance using a the default comparer for the property type.
/// </summary>
/// <param name="property"> The property to use for comparisons. </param>
public EntryCurrentValueComparer([NotNull] IPropertyBase property)
{
_property = property;
_underlyingComparer = Comparer<TProperty>.Default;
}

/// <summary>
/// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
/// </summary>
/// <param name="x"> The first object to compare. </param>
/// <param name="y"> The second object to compare. </param>
/// <returns> A negative number if 'x' is less than 'y'; a positive number if 'x' is greater than 'y'; zero otherwise. </returns>
public int Compare(IUpdateEntry x, IUpdateEntry y)
=> _underlyingComparer.Compare(
x.GetCurrentValue<TProperty>(_property),
y.GetCurrentValue<TProperty>(_property));

/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
/// <param name="x"> The first object to compare. </param>
/// <param name="y"> The second object to compare. </param>
/// <returns> True if the specified objects are equal; otherwise, false. </returns>
public bool Equals(IUpdateEntry x, IUpdateEntry y)
=> Compare(x, y) == 0;

/// <summary>
/// Returns a hash code for the specified object.
/// </summary>
/// <param name="obj"> The for which a hash code is to be returned. </param>
/// <returns> A hash code for the specified object. </returns>
public int GetHashCode(IUpdateEntry obj)
=> obj.GetCurrentValue<TProperty>(_property).GetHashCode();
}
}
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/ChangeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.DependencyInjection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ public virtual IComparer<IUpdateEntry> Create([NotNull] IPropertyBase propertyBa
if (IsGenericComparable(modelType, nonNullableModelType))
{
return (IComparer<IUpdateEntry>)Activator.CreateInstance(
typeof(CurrentValueComparer<>).MakeGenericType(modelType),
typeof(EntryCurrentValueComparer<>).MakeGenericType(modelType),
propertyBase);
}

if (typeof(IStructuralComparable).IsAssignableFrom(nonNullableModelType))
{
return new StructuralCurrentValueComparer(propertyBase);
return new StructuralEntryCurrentValueComparer(propertyBase);
}

if (typeof(IComparable).IsAssignableFrom(nonNullableModelType))
{
return new CurrentValueComparer(propertyBase);
return new EntryCurrentValueComparer(propertyBase);
}

if (propertyBase is IProperty property)
Expand All @@ -71,12 +71,12 @@ public virtual IComparer<IUpdateEntry> Create([NotNull] IPropertyBase propertyBa

if (typeof(IStructuralComparable).IsAssignableFrom(nonNullableProviderType))
{
return new StructuralCurrentProviderValueComparer(propertyBase, converter);
return new StructuralEntryCurrentProviderValueComparer(propertyBase, converter);
}

if (typeof(IComparable).IsAssignableFrom(nonNullableProviderType))
{
return new CurrentProviderValueComparer(propertyBase, converter);
return new EntryCurrentProviderValueComparer(propertyBase, converter);
}

throw new InvalidOperationException(
Expand Down
45 changes: 0 additions & 45 deletions src/EFCore/ChangeTracking/Internal/CurrentValueComparer`.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal
/// 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 class CurrentProviderValueComparer : CurrentValueComparer
public class EntryCurrentProviderValueComparer : EntryCurrentValueComparer
{
private readonly ValueConverter _converter;

Expand All @@ -24,7 +24,7 @@ public class CurrentProviderValueComparer : CurrentValueComparer
/// 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 CurrentProviderValueComparer(
public EntryCurrentProviderValueComparer(
[NotNull] IPropertyBase property,
[NotNull] ValueConverter converter)
: base(property)
Expand All @@ -38,7 +38,7 @@ public CurrentProviderValueComparer(
/// 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 override object GetCurrentValue(IUpdateEntry entry)
=> _converter.ConvertToProvider(base.GetCurrentValue(entry));
protected override object GetPropertyValue(IUpdateEntry entry)
=> _converter.ConvertToProvider(base.GetPropertyValue(entry));
}
}
Loading

0 comments on commit fd33e46

Please sign in to comment.