@@ -593,60 +593,86 @@ public override void EnlistTransaction(Transaction transaction)
593593 #region Close
594594
595595 /// <summary>
596- /// releases the connection to the database. If the connection is pooled, it will be
597- /// made available for re-use. If it is non-pooled, the actual connection will be shutdown .
596+ /// Releases the connection. If the connection is pooled, it will be returned to the pull and made available for re-use.
597+ /// If it is non-pooled, the physical connection will be closed .
598598 /// </summary>
599- public override void Close ( ) => Close ( false ) ;
599+ public override void Close ( ) => Close ( wasBroken : false , async : false ) ;
600600
601- internal void Close ( bool wasBroken )
601+ /// <summary>
602+ /// Releases the connection. If the connection is pooled, it will be returned to the pull and made available for re-use.
603+ /// If it is non-pooled, the physical connection will be closed.
604+ /// </summary>
605+ #if ! NET461 && ! NETSTANDARD2_0
606+ public override Task CloseAsync ( )
607+ #else
608+ public Task CloseAsync ( )
609+ #endif
610+ {
611+ using ( NoSynchronizationContextScope . Enter ( ) )
612+ return Close ( wasBroken : false , async: true ) ;
613+ }
614+
615+ internal Task Close ( bool wasBroken , bool async )
602616 {
603617 if ( Connector == null )
604- return ;
618+ return Task . CompletedTask ;
605619 var connectorId = Connector . Id ;
606620 Log . Trace ( "Closing connection..." , connectorId ) ;
607621 _wasBroken = wasBroken ;
608622
609- Connector . CloseOngoingOperations ( ) ;
623+ if ( Connector . HasOngoingOperation )
624+ return CloseOngoingOperationAndFinish ( ) ;
610625
611- // The connector has closed us during CloseOngoingOperations due to an underlying failure.
612- if ( Connector == null )
613- return ;
626+ FinishClose ( ) ;
627+ return Task . CompletedTask ;
614628
615- if ( Settings . Pooling )
629+ async Task CloseOngoingOperationAndFinish ( )
616630 {
617- if ( EnlistedTransaction == null )
618- _pool ! . Release ( Connector ) ;
619- else
631+ await Connector ! . CloseOngoingOperations ( async) ;
632+
633+ // The connector has closed us during CloseOngoingOperations due to an underlying failure.
634+ if ( Connector == null )
635+ return ;
636+
637+ FinishClose ( ) ;
638+ }
639+
640+ void FinishClose ( )
641+ {
642+ var connector = Connector ! ;
643+ if ( Settings . Pooling )
620644 {
621- // A System.Transactions transaction is still in progress, we need to wait for it to complete.
622- // Close the connection and disconnect it from the resource manager but leave the connector
623- // in a enlisted pending list in the pool.
624- _pool ! . AddPendingEnlistedConnector ( Connector , EnlistedTransaction ) ;
625- Connector . Connection = null ;
645+ if ( EnlistedTransaction == null )
646+ _pool ! . Release ( connector ) ;
647+ else
648+ {
649+ // A System.Transactions transaction is still in progress, we need to wait for it to complete.
650+ // Close the connection and disconnect it from the resource manager but leave the connector
651+ // in a enlisted pending list in the pool.
652+ _pool ! . AddPendingEnlistedConnector ( connector , EnlistedTransaction ) ;
653+ connector . Connection = null ;
654+ EnlistedTransaction = null ;
655+ }
656+ }
657+ else // Non-pooled connection
658+ {
659+ if ( EnlistedTransaction == null )
660+ connector . Close ( ) ;
661+ // If a non-pooled connection is being closed but is enlisted in an ongoing
662+ // TransactionScope, simply detach the connector from the connection and leave
663+ // it open. It will be closed when the TransactionScope is disposed.
664+ connector . Connection = null ;
626665 EnlistedTransaction = null ;
627666 }
628- }
629- else // Non-pooled connection
630- {
631- if ( EnlistedTransaction == null )
632- Connector . Close ( ) ;
633- // If a non-pooled connection is being closed but is enlisted in an ongoing
634- // TransactionScope, simply detach the connector from the connection and leave
635- // it open. It will be closed when the TransactionScope is disposed.
636- Connector . Connection = null ;
637- EnlistedTransaction = null ;
638- }
639-
640- Log . Debug ( "Connection closed" , connectorId ) ;
641667
642- Connector = null ;
643-
644- OnStateChange ( OpenToClosedEventArgs ) ;
668+ Log . Debug ( "Connection closed" , connectorId ) ;
669+ Connector = null ;
670+ OnStateChange ( OpenToClosedEventArgs ) ;
671+ }
645672 }
646673
647674 /// <summary>
648- /// Releases all resources used by the
649- /// <see cref="NpgsqlConnection">NpgsqlConnection</see>.
675+ /// Releases all resources used by the <see cref="NpgsqlConnection">NpgsqlConnection</see>.
650676 /// </summary>
651677 /// <param name="disposing"><b>true</b> when called from Dispose();
652678 /// <b>false</b> when being called from the finalizer.</param>
@@ -656,10 +682,22 @@ protected override void Dispose(bool disposing)
656682 return ;
657683 if ( disposing )
658684 Close ( ) ;
659- base . Dispose ( disposing ) ;
660685 _disposed = true ;
661686 }
662687
688+ #if ! NET461 && ! NETSTANDARD2_0
689+ /// <summary>
690+ /// Releases all resources used by the <see cref="NpgsqlConnection">NpgsqlConnection</see>.
691+ /// </summary>
692+ public override async ValueTask DisposeAsync ( )
693+ {
694+ if ( _disposed )
695+ return ;
696+ await CloseAsync ( ) ;
697+ _disposed = true ;
698+ }
699+ #endif
700+
663701 #endregion
664702
665703 #region Notifications and Notices
0 commit comments