@@ -314,26 +314,7 @@ async Task OpenAsync(bool async, CancellationToken cancellationToken)
314314 enlistToTransaction = null ;
315315 }
316316 else
317- while ( true )
318- {
319- try
320- {
321- connector = await _dataSource . Get ( this , timeout , async, cancellationToken ) ;
322- break ;
323- }
324- // When using PoolManager (legacy code path setting NpgsqlConnection.ConnectionString), clearing a pool
325- // removes the pool (NpgsqlDataSource) from the PoolManager and disposes it.
326- // This leads to an ObjectDisposedException when calling NpgsqlDataSource.Get() here.
327- // If this happens we reinitialize the pool and add it to the PoolManager by calling SetupDataSource() again.
328- // When not using PoolManager (modern code path creating the NpgsqlConnection from a NpgsqlDataSource;
329- // _retryDisposedDataSource is false) we bubble up an eventual ObjectDisposedException as usual.
330- catch ( ObjectDisposedException )
331- {
332- if ( ! _retryDisposedDataSource )
333- throw ;
334- SetupDataSource ( ) ;
335- }
336- }
317+ connector = await GetConnector ( timeout , async , cancellationToken ) ;
337318
338319 Debug. Assert( connector . Connection is null,
339320 $"Connection for opened connector '{Connector?.Id.ToString() ?? " ?? ? "}' is bound to another connection" ) ;
@@ -386,6 +367,29 @@ async Task PerformMultiplexingStartupCheck(bool async, CancellationToken cancell
386367 }
387368 }
388369 }
370+ async Task < NpgsqlConnector > GetConnector ( NpgsqlTimeout timeout , bool async , CancellationToken cancellationToken )
371+ {
372+ while ( true )
373+ {
374+ try
375+ {
376+ Debug . Assert ( _dataSource != null ) ;
377+ return await _dataSource . Get ( this , timeout , async, cancellationToken ) ;
378+ }
379+ // When using PoolManager (legacy code path setting NpgsqlConnection.ConnectionString), clearing a pool
380+ // removes the pool (NpgsqlDataSource) from the PoolManager and disposes it.
381+ // This leads to an ObjectDisposedException when calling NpgsqlDataSource.Get() here.
382+ // If this happens we reinitialize the pool and add it to the PoolManager by calling SetupDataSource() again.
383+ // When not using PoolManager (modern code path creating the NpgsqlConnection from a NpgsqlDataSource;
384+ // _retryDisposedDataSource is false) we bubble up an eventual ObjectDisposedException as usual.
385+ catch ( ObjectDisposedException )
386+ {
387+ if ( ! _retryDisposedDataSource )
388+ throw ;
389+ SetupDataSource ( ) ;
390+ }
391+ }
392+ }
389393
390394 #endregion Open / Init
391395
@@ -1653,7 +1657,7 @@ async ValueTask<NpgsqlConnector> StartBindingScopeAsync()
16531657 Debug . Assert ( Settings . Multiplexing ) ;
16541658 Debug . Assert ( _dataSource != null ) ;
16551659
1656- var connector = await _dataSource . Get ( this , timeout , async, cancellationToken ) ;
1660+ var connector = await GetConnector ( timeout , async , cancellationToken ) ;
16571661 Connector = connector ;
16581662 connector . Connection = this ;
16591663 ConnectorBindingScope = scope ;
@@ -1905,32 +1909,49 @@ public void ReloadTypes()
19051909 CheckReady ( ) ;
19061910
19071911 using var scope = StartTemporaryBindingScope ( out var connector ) ;
1908-
1909- _dataSource ! . Bootstrap (
1910- connector ,
1911- NpgsqlTimeout . Infinite ,
1912- forceReload : true ,
1913- async: false ,
1914- CancellationToken . None )
1915- . GetAwaiter ( ) . GetResult ( ) ;
1912+ BootstrapDataSource ( connector , async: false ) . GetAwaiter ( ) . GetResult ( ) ;
19161913 }
19171914
19181915 /// <summary>
19191916 /// Flushes the type cache for this connection's connection string and reloads the types for this connection only.
19201917 /// Type changes will appear for other connections only after they are re-opened from the pool.
19211918 /// </summary>
1922- public async Task ReloadTypesAsync ( )
1919+ public Task ReloadTypesAsync ( )
19231920 {
1921+ using var _ = NoSynchronizationContextScope . Enter ( ) ;
19241922 CheckReady ( ) ;
19251923
19261924 using var scope = StartTemporaryBindingScope ( out var connector ) ;
1925+ return BootstrapDataSource ( connector , async: true ) ;
1926+ }
19271927
1928- await _dataSource ! . Bootstrap (
1929- connector ,
1930- NpgsqlTimeout . Infinite ,
1931- forceReload : true ,
1932- async: true ,
1933- CancellationToken . None ) ;
1928+ async Task BootstrapDataSource ( NpgsqlConnector connector , bool async )
1929+ {
1930+ while ( true )
1931+ {
1932+ try
1933+ {
1934+ await _dataSource ! . Bootstrap (
1935+ connector ,
1936+ NpgsqlTimeout . Infinite ,
1937+ forceReload : true ,
1938+ async,
1939+ CancellationToken . None ) ;
1940+ break ;
1941+ }
1942+ // When using PoolManager (legacy code path setting NpgsqlConnection.ConnectionString), clearing a pool
1943+ // removes the pool (NpgsqlDataSource) from the PoolManager and disposes it.
1944+ // This leads to an ObjectDisposedException when calling NpgsqlDataSource.Get() here.
1945+ // If this happens we reinitialize the pool and add it to the PoolManager by calling SetupDataSource() again.
1946+ // When not using PoolManager (modern code path creating the NpgsqlConnection from a NpgsqlDataSource;
1947+ // _retryDisposedDataSource is false) we bubble up an eventual ObjectDisposedException as usual.
1948+ catch ( ObjectDisposedException )
1949+ {
1950+ if ( ! _retryDisposedDataSource )
1951+ throw ;
1952+ SetupDataSource ( ) ;
1953+ }
1954+ }
19341955 }
19351956
19361957 /// <summary>
0 commit comments