diff --git a/src/Npgsql/NpgsqlConnection.cs b/src/Npgsql/NpgsqlConnection.cs
index ac1df9a132..aa27a2c5d0 100644
--- a/src/Npgsql/NpgsqlConnection.cs
+++ b/src/Npgsql/NpgsqlConnection.cs
@@ -134,6 +134,9 @@ public sealed class NpgsqlConnection : DbConnection, ICloneable
private NpgsqlPromotableSinglePhaseNotification promotable = null;
+ // A cached copy of the result of `settings.ConnectionString`
+ private string _connectionString;
+
///
/// Initializes a new instance of the
@@ -154,18 +157,8 @@ public NpgsqlConnection(String ConnectionString)
{
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, "NpgsqlConnection()");
- NpgsqlConnectionStringBuilder builder = cache[ConnectionString];
- if (builder == null)
- {
- settings = new NpgsqlConnectionStringBuilder(ConnectionString);
- }
- else
- {
- settings = builder.Clone();
- }
-
- LogConnectionString();
-
+ LoadConnectionStringBuilder(ConnectionString);
+
NoticeDelegate = new NoticeEventHandler(OnNotice);
NotificationDelegate = new NotificationEventHandler(OnNotification);
@@ -246,9 +239,14 @@ public NpgsqlConnection(String ConnectionString)
[Editor(typeof(ConnectionStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
#endif
- public override String ConnectionString
- {
- get { return settings.ConnectionString; }
+ public override String ConnectionString
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(_connectionString))
+ RefreshConnectionString();
+ return settings.ConnectionString;
+ }
set
{
// Connection string is used as the key to the connector. Because of this,
@@ -264,7 +262,7 @@ public override String ConnectionString
{
settings = builder.Clone();
}
- LogConnectionString();
+ LoadConnectionStringBuilder(value);
}
}
@@ -606,7 +604,10 @@ public override void ChangeDatabase(String dbName)
Close();
- settings[Keywords.Database] = dbName;
+ // Mutating the current `settings` object would invalidate the cached instance, so work on a copy instead.
+ settings = settings.Clone();
+ settings[Keywords.Database] = dbName;
+ _connectionString = null;
Open();
}
@@ -781,6 +782,14 @@ internal void OnNotification(object O, NpgsqlNotificationEventArgs E)
}
}
+ ///
+ /// Returns a copy of the NpgsqlConnectionStringBuilder that contains the parsed connection string values.
+ ///
+ internal NpgsqlConnectionStringBuilder CopyConnectionStringBuilder()
+ {
+ return settings.Clone();
+ }
+
///
/// The connector object connected to the backend.
///
@@ -930,12 +939,40 @@ private NpgsqlPromotableSinglePhaseNotification Promotable
///
private void LogConnectionString()
{
+ if (LogLevel.Debug >= NpgsqlEventLog.Level)
+ return;
+
foreach (string key in settings.Keys)
{
NpgsqlEventLog.LogMsg(resman, "Log_ConnectionStringValues", LogLevel.Debug, key, settings[key]);
}
}
+ ///
+ /// Sets the `settings` ConnectionStringBuilder based on the given `connectionString`
+ ///
+ /// The connection string to load the builder from
+ private void LoadConnectionStringBuilder(string connectionString)
+ {
+ settings = cache[connectionString];
+ if (settings == null)
+ {
+ settings = new NpgsqlConnectionStringBuilder(connectionString);
+ cache[connectionString] = settings;
+ }
+
+ RefreshConnectionString();
+ LogConnectionString();
+ }
+
+ ///
+ /// Refresh the cached _connectionString whenever the builder settings change
+ ///
+ private void RefreshConnectionString()
+ {
+ _connectionString = settings.ConnectionString;
+ }
+
private void CheckConnectionOpen()
{
if (disposed)
diff --git a/src/Npgsql/NpgsqlConnector.cs b/src/Npgsql/NpgsqlConnector.cs
index 92b6778e87..7906711dba 100644
--- a/src/Npgsql/NpgsqlConnector.cs
+++ b/src/Npgsql/NpgsqlConnector.cs
@@ -165,12 +165,12 @@ internal SSPIHandler SSPI
set { _sspi = value; }
}
-#endif
-
- public NpgsqlConnector(NpgsqlConnection Connection)
- : this(Connection.ConnectionStringValues.Clone(), Connection.Pooling, false)
- {}
-
+#endif
+
+ public NpgsqlConnector(NpgsqlConnection Connection)
+ : this(Connection.CopyConnectionStringBuilder(), Connection.Pooling, false)
+ {}
+
///
/// Constructor.
///