From a5a67c4d0ca9339b97d6c2aaa6f88d4b8b67fb13 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 15 Aug 2022 16:07:48 +0200 Subject: [PATCH] Perform structural equality in ExpressionEqualityComparer Fixes #28581 --- .../Query/ExpressionEqualityComparer.cs | 24 +++++++++++++++---- .../Query/ExpressionEqualityComparerTest.cs | 16 +++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/EFCore/Query/ExpressionEqualityComparer.cs b/src/EFCore/Query/ExpressionEqualityComparer.cs index bd8934fee4d..fd4bfd809ad 100644 --- a/src/EFCore/Query/ExpressionEqualityComparer.cs +++ b/src/EFCore/Query/ExpressionEqualityComparer.cs @@ -5,6 +5,8 @@ // ReSharper disable ForCanBeConvertedToForeach // ReSharper disable LoopCanBeConvertedToQuery +using System.Collections; + namespace Microsoft.EntityFrameworkCore.Query; /// @@ -64,10 +66,19 @@ public int GetHashCode(Expression obj) break; case ConstantExpression constantExpression: - if (constantExpression.Value != null - && !(constantExpression.Value is IQueryable)) + switch (constantExpression.Value) { - hash.Add(constantExpression.Value); + case IQueryable: + case null: + break; + + case IStructuralEquatable structuralEquatable: + hash.Add(structuralEquatable.GetHashCode(StructuralComparisons.StructuralEqualityComparer)); + break; + + default: + hash.Add(constantExpression.Value); + break; } break; @@ -354,7 +365,12 @@ private bool CompareConditional(ConditionalExpression a, ConditionalExpression b && Compare(a.IfFalse, b.IfFalse); private static bool CompareConstant(ConstantExpression a, ConstantExpression b) - => Equals(a.Value, b.Value); + { + var (v1, v2) = (a.Value, b.Value); + + return Equals(v1, v2) + || (v1 is IStructuralEquatable array1 && array1.Equals(v2, StructuralComparisons.StructuralEqualityComparer)); + } private bool CompareGoto(GotoExpression a, GotoExpression b) => a.Kind == b.Kind diff --git a/test/EFCore.Tests/Query/ExpressionEqualityComparerTest.cs b/test/EFCore.Tests/Query/ExpressionEqualityComparerTest.cs index 72f5ac01b21..7f61dfa7bdd 100644 --- a/test/EFCore.Tests/Query/ExpressionEqualityComparerTest.cs +++ b/test/EFCore.Tests/Query/ExpressionEqualityComparerTest.cs @@ -94,6 +94,22 @@ public void Index_expressions_are_compared_correctly() Assert.True(expressionComparer.Equals(e2, e3)); } + [ConditionalFact] + public void Array_constant_expressions_are_compared_correctly() + { + var expressionComparer = ExpressionEqualityComparer.Instance; + + var e1 = Expression.Constant(new[] { 1, 2, 3 }); + var e2 = Expression.Constant(new[] { 1, 2, 3 }); + var e3 = Expression.Constant(new[] { 1, 2, 4 }); + + Assert.True(expressionComparer.Equals(e1, e2)); + Assert.False(expressionComparer.Equals(e1, e3)); + + Assert.Equal(expressionComparer.GetHashCode(e1), expressionComparer.GetHashCode(e2)); + Assert.NotEqual(expressionComparer.GetHashCode(e1), expressionComparer.GetHashCode(e3)); + } + private class Node { [UsedImplicitly]