11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System . Collections ;
54using System . Collections . Concurrent ;
65using System . Runtime . CompilerServices ;
76using Microsoft . Extensions . Caching . Memory ;
@@ -106,11 +105,25 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter)
106105 }
107106 }
108107
109- private readonly struct CommandCacheKey ( Expression queryExpression , IReadOnlyDictionary < string , object ? > parameterValues )
110- : IEquatable < CommandCacheKey >
108+ private readonly struct CommandCacheKey : IEquatable < CommandCacheKey >
111109 {
112- private readonly Expression _queryExpression = queryExpression ;
113- private readonly IReadOnlyDictionary < string , object ? > _parameterValues = parameterValues ;
110+ private readonly Expression _queryExpression ;
111+ private readonly Dictionary < string , ParameterInfo > _parameterInfos ;
112+
113+ internal CommandCacheKey ( Expression queryExpression , IReadOnlyDictionary < string , object ? > parameterValues )
114+ {
115+ _queryExpression = queryExpression ;
116+ _parameterInfos = new Dictionary < string , ParameterInfo > ( ) ;
117+
118+ foreach ( var ( key , value ) in parameterValues )
119+ {
120+ _parameterInfos [ key ] = new ParameterInfo
121+ {
122+ IsNull = value is null ,
123+ ObjectArrayLength = value is object [ ] arr ? arr . Length : null
124+ } ;
125+ }
126+ }
114127
115128 public override bool Equals ( object ? obj )
116129 => obj is CommandCacheKey commandCacheKey
@@ -124,27 +137,18 @@ public bool Equals(CommandCacheKey commandCacheKey)
124137 return false ;
125138 }
126139
127- if ( _parameterValues . Count > 0 )
140+ Check . DebugAssert (
141+ _parameterInfos . Count == commandCacheKey . _parameterInfos . Count ,
142+ "Parameter Count mismatch between identical queries" ) ;
143+
144+ if ( _parameterInfos . Count > 0 )
128145 {
129- foreach ( var ( key , value ) in _parameterValues )
146+ foreach ( var ( key , info ) in _parameterInfos )
130147 {
131- if ( ! commandCacheKey . _parameterValues . TryGetValue ( key , out var otherValue ) )
148+ if ( ! commandCacheKey . _parameterInfos . TryGetValue ( key , out var otherInfo ) || info != otherInfo )
132149 {
133150 return false ;
134151 }
135-
136- // ReSharper disable once ArrangeRedundantParentheses
137- if ( ( value == null ) != ( otherValue == null ) )
138- {
139- return false ;
140- }
141-
142- if ( value is IEnumerable
143- && value . GetType ( ) == typeof ( object [ ] ) )
144- {
145- // FromSql parameters must have the same number of elements
146- return ( ( object [ ] ) value ) . Length == ( otherValue as object [ ] ) ? . Length ;
147- }
148152 }
149153 }
150154
@@ -154,4 +158,8 @@ public bool Equals(CommandCacheKey commandCacheKey)
154158 public override int GetHashCode ( )
155159 => RuntimeHelpers . GetHashCode ( _queryExpression ) ;
156160 }
161+
162+ // Note that we keep only the null-ness of parameters (and array length for FromSql object arrays),
163+ // and avoid referencing the actual parameter data (see #34028).
164+ private readonly record struct ParameterInfo ( bool IsNull , int ? ObjectArrayLength ) ;
157165}
0 commit comments