Edit:
@Jeroen Mostert's comment worked well: adding Pooling=false to the connection string. As he/she noted, I have to read some more about this additions impact on overall performance.
- Lang: C#
- DBMS: Postgres
In the code below with two consecutive using blocks (much has been deleted to make it clear);
- In the first
usingblock, before dropping the databasecamsdb, I connect to the database for the last time and do a final query. - After the query, the code exits the first
usingblock and is supposed to close the database connection. - Unfortunately, the second
usingblock (which is supposed to drop the database that was just connected to in the first using block) fails to drop the database. ThePostgresExceptionsays "There is 1 other session using the database."
However, when I comment out the first using block, the second using block —fulfilling its duty— drops the database without any problem. Isn't that using block supposed to close the connection when the code reaches the related curly brace? Is there a way to force the Garbage Collector to clean the connection immediately? (Any other solutions are welcome.)
private M_SqlConn m_sqlConn = null; // predefined
...
...
// *** using block no: 1 ***
using (m_sqlConn = new M_SqlConn("127.0.0.1", 5432, "camsdb", "my_user_name", "my_password")) {
// perform a last sql query
}
// *** using block no: 2 ***
using (m_sqlConn = new M_SqlConn("127.0.0.1", 5432, "postgres", "postgres", "admin_password")) {
if (this.DbDrop("camsdb")) {
FormWarn_ShowDialog(FormWarn.FormType.Info, "db dropped succesfully ...")
}
else {
FormWarn_ShowDialog(FormWarn.FormType.Error, "can not drop db !!!")
}
}
The M_SqlConn class as a whole is below (didn't want to mess up the page, that's why I didn't paste it at first):
using Npgsql;
using System;
using System.Text;
internal class M_SqlConn : IDisposable {
public Boolean connectionIsOpen = false;
private FormWarn formWarn = null;
private NpgsqlConnection sqlConnection = null;
private String hostAddress = "";
private String portNumber = "";
private String dbName = "";
private String roleName = "";
private String password = "";
internal M_SqlConn(String hostAddress, String portNumber, String dbName, String roleName, String password) {
this.hostAddress = hostAddress;
this.portNumber = portNumber;
this.dbName = dbName;
this.roleName = roleName;
this.password = password;
this.ConnectionOpen();
return;
}
private void ConnectionOpen() {
StringBuilder exceptionString = new StringBuilder(String.Empty);
NpgsqlConnectionStringBuilder connectionStringBuilder = new NpgsqlConnectionStringBuilder {
Host = this.hostAddress,
Port = Convert.ToInt32(this.portNumber),
Database = this.dbName,
Username = this.roleName
};
this.sqlConnection = new NpgsqlConnection(connectionStringBuilder.ToString() + $";Password={this.password}");
try {
this.sqlConnection.Open();
if (this.sqlConnection.State == System.Data.ConnectionState.Open) {
this.connectionIsOpen = true;
}
}
catch (PostgresException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Postgres Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (NpgsqlException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Npgsql Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (Exception e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"General Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
if (!this.connectionIsOpen) {
this.FormWarn_ShowDialog(FormWarn.FormType.Error, exceptionString.ToString());
}
return;
}
private void ConnectionClose() {
StringBuilder exceptionString = new StringBuilder(String.Empty);
if (this.sqlConnection != null) {
try {
this.sqlConnection.Close();
this.connectionIsOpen = false;
}
catch (PostgresException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Postgres Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (NpgsqlException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Npgsql Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (Exception e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"General Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
if (this.connectionIsOpen) {
this.FormWarn_ShowDialog(FormWarn.FormType.Error, exceptionString.ToString());
}
else {
this.sqlConnection.Dispose();
this.sqlConnection = null;
}
}
return;
}
public Boolean SqlCommandExecuteNonQuery(String sqlString) {
Boolean commandStatus = false;
StringBuilder exceptionString = new StringBuilder(String.Empty);
using (NpgsqlCommand sqlCommand = new NpgsqlCommand(sqlString, this.sqlConnection)) {
try {
sqlCommand.ExecuteNonQuery();
commandStatus = true;
}
catch (PostgresException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Postgres Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (NpgsqlException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Npgsql Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (Exception e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"General Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
};
if (!commandStatus) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Sql string is:{Environment.NewLine}" +
$"{sqlString}{Environment.NewLine}");
this.FormWarn_ShowDialog(FormWarn.FormType.Error, exceptionString.ToString());
}
return (commandStatus);
}
public Int32 SqlCommandExecuteScalar(String sqlString) {
Int32 count = -1;
StringBuilder exceptionString = new StringBuilder(String.Empty);
using (NpgsqlCommand sqlCommand = new NpgsqlCommand(sqlString, this.sqlConnection)) {
try {
Int32 countTmp = Convert.ToInt32(sqlCommand.ExecuteScalar());
count = countTmp;
}
catch (PostgresException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Postgres Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (NpgsqlException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Npgsql Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (Exception e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"General Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
};
if (count == -1) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Sql string is:{Environment.NewLine}" +
$"{sqlString}{Environment.NewLine}");
this.FormWarn_ShowDialog(FormWarn.FormType.Error, exceptionString.ToString());
}
return (count);
}
public NpgsqlDataReader SqlCommandExecuteQuery(String sqlString) {
NpgsqlDataReader dataReader = null;
StringBuilder exceptionString = new StringBuilder(String.Empty);
using (NpgsqlCommand sqlCommand = new NpgsqlCommand(sqlString, this.sqlConnection)) {
try {
dataReader = sqlCommand.ExecuteReader();
}
catch (PostgresException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Postgres Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (NpgsqlException e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Npgsql Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
catch (Exception e) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"General Exception{Environment.NewLine}" +
$"{e.ToString()}{Environment.NewLine}");
}
};
if (exceptionString.Length > 0) {
exceptionString.AppendLine(
$"{Environment.NewLine}" +
$"Sql string is:{Environment.NewLine}" +
$"{sqlString}{Environment.NewLine}");
this.FormWarn_ShowDialog(FormWarn.FormType.Error, exceptionString.ToString());
}
return (dataReader);
}
private void FormWarn_ShowDialog(FormWarn.FormType formType, String msg) {
using (this.formWarn = new FormWarn(formType, msg)) {
this.formWarn.ShowDialog();
}
this.formWarn.Dispose();
this.formWarn = null;
return;
}
public void Dispose() {
if (this.formWarn != null) {
this.formWarn.Dispose();
this.formWarn = null;
}
if (this.connectionIsOpen) {
this.ConnectionClose();
}
this.hostAddress = "";
this.portNumber = "";
this.dbName = "";
this.roleName = "";
this.password = "";
return;
}
}
I've tried @Panagiotis's trick but it didn't work. Changed the if block to the below but this time the program halted giving "System.NullReferenceException: 'Object reference not set to an instance of an object.'"
if (this.sqlConnection.State == System.Data.ConnectionState.Open) {
this.sqlConnection.Dispose(); // exception here
this.sqlConnection = null;
}
M_SqlConn? That's not a standard type.Disposelogic, or else the Postgres database provider keeps the (physical) connection pooled. There are typically ways to turn that off for a specific connection, but that depends on the connection library used. (Clearing the connection pool is another approach, but that's a global solution to a local problem.)usingblock, so not only can you useDispose()on it, it's the only thing guaranteed to always workNpgSqlConnectionsupports connection pooling; if the "open session" persists despite disposing everything, create a non-pooled connection by passingPooling = falseto the connection string builder for that connection only. Take care not to make this a global default, as that would negatively impact performance for most applications.