@@ -161,6 +161,103 @@ internal SqlInternalConnectionTds CreatePooledConnection(
161
161
return newConnection ;
162
162
}
163
163
164
+ internal DbConnectionPoolGroup GetConnectionPoolGroup (
165
+ DbConnectionPoolKey key ,
166
+ DbConnectionPoolGroupOptions poolOptions ,
167
+ ref DbConnectionOptions userConnectionOptions )
168
+ {
169
+ if ( string . IsNullOrEmpty ( key . ConnectionString ) )
170
+ {
171
+ return null ;
172
+ }
173
+
174
+ if ( ! _connectionPoolGroups . TryGetValue ( key , out DbConnectionPoolGroup connectionPoolGroup ) ||
175
+ ( connectionPoolGroup . IsDisabled && connectionPoolGroup . PoolGroupOptions != null ) )
176
+ {
177
+ // If we can't find an entry for the connection string in
178
+ // our collection of pool entries, then we need to create a
179
+ // new pool entry and add it to our collection.
180
+
181
+ DbConnectionOptions connectionOptions = CreateConnectionOptions (
182
+ key . ConnectionString ,
183
+ userConnectionOptions ) ;
184
+ if ( connectionOptions is null )
185
+ {
186
+ throw ADP . InternalConnectionError ( ADP . ConnectionError . ConnectionOptionsMissing ) ;
187
+ }
188
+
189
+ if ( userConnectionOptions is null )
190
+ {
191
+ // We only allow one expansion on the connection string
192
+ userConnectionOptions = connectionOptions ;
193
+ string expandedConnectionString = connectionOptions . Expand ( ) ;
194
+
195
+ // if the expanded string is same instance (default implementation), then use the already created options
196
+ if ( ( object ) expandedConnectionString != ( object ) key . ConnectionString )
197
+ {
198
+ // CONSIDER: caching the original string to reduce future parsing
199
+ DbConnectionPoolKey newKey = ( DbConnectionPoolKey ) key . Clone ( ) ;
200
+ newKey . ConnectionString = expandedConnectionString ;
201
+ return GetConnectionPoolGroup ( newKey , null , ref userConnectionOptions ) ;
202
+ }
203
+ }
204
+
205
+ if ( poolOptions is null )
206
+ {
207
+ if ( connectionPoolGroup is not null )
208
+ {
209
+ // reusing existing pool option in case user originally used SetConnectionPoolOptions
210
+ poolOptions = connectionPoolGroup . PoolGroupOptions ;
211
+ }
212
+ else
213
+ {
214
+ // Note: may return null for non-pooled connections
215
+ poolOptions = CreateConnectionPoolGroupOptions ( connectionOptions ) ;
216
+ }
217
+ }
218
+
219
+ lock ( this )
220
+ {
221
+ if ( ! _connectionPoolGroups . TryGetValue ( key , out connectionPoolGroup ) )
222
+ {
223
+ DbConnectionPoolGroup newConnectionPoolGroup =
224
+ new DbConnectionPoolGroup ( connectionOptions , key , poolOptions )
225
+ {
226
+ ProviderInfo = CreateConnectionPoolGroupProviderInfo ( connectionOptions )
227
+ } ;
228
+
229
+ // build new dictionary with space for new connection string
230
+ Dictionary < DbConnectionPoolKey , DbConnectionPoolGroup > newConnectionPoolGroups =
231
+ new Dictionary < DbConnectionPoolKey , DbConnectionPoolGroup > ( 1 + _connectionPoolGroups . Count ) ;
232
+ foreach ( KeyValuePair < DbConnectionPoolKey , DbConnectionPoolGroup > entry in _connectionPoolGroups )
233
+ {
234
+ newConnectionPoolGroups . Add ( entry . Key , entry . Value ) ;
235
+ }
236
+
237
+ // lock prevents race condition with PruneConnectionPoolGroups
238
+ newConnectionPoolGroups . Add ( key , newConnectionPoolGroup ) ;
239
+
240
+ SqlClientEventSource . Metrics . EnterActiveConnectionPoolGroup ( ) ;
241
+ connectionPoolGroup = newConnectionPoolGroup ;
242
+ _connectionPoolGroups = newConnectionPoolGroups ;
243
+ }
244
+ else
245
+ {
246
+ Debug . Assert ( ! connectionPoolGroup . IsDisabled , "Disabled pool entry discovered" ) ;
247
+ }
248
+ }
249
+
250
+ Debug . Assert ( connectionPoolGroup != null , "how did we not create a pool entry?" ) ;
251
+ Debug . Assert ( userConnectionOptions != null , "how did we not have user connection options?" ) ;
252
+ }
253
+ else if ( userConnectionOptions is null )
254
+ {
255
+ userConnectionOptions = connectionPoolGroup . ConnectionOptions ;
256
+ }
257
+
258
+ return connectionPoolGroup ;
259
+ }
260
+
164
261
internal void QueuePoolForRelease ( IDbConnectionPool pool , bool clearing )
165
262
{
166
263
// Queue the pool up for release -- we'll clear it out and dispose of it as the last
@@ -705,6 +802,8 @@ private IDbConnectionPool GetConnectionPool(
705
802
return connectionPool ;
706
803
}
707
804
805
+
806
+
708
807
private void TryGetConnectionCompletedContinuation ( Task < DbConnectionInternal > task , object state )
709
808
{
710
809
// Decompose the state into the parameters we want
0 commit comments