Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个'using'块不能释放数据库连接?_C#_Sql_Postgresql_Npgsql - Fatal编程技术网

C# 为什么这个'using'块不能释放数据库连接?

C# 为什么这个'using'块不能释放数据库连接?,c#,sql,postgresql,npgsql,C#,Sql,Postgresql,Npgsql,编辑: @Jeroen Mostert的评论效果很好:向连接字符串添加Pooling=false。正如他/她所指出的,我必须多读一些关于这种添加对整体性能的影响的文章 朗:C# 数据库管理系统:Postgres 在下面的代码中,使用两个连续的块(为了清楚起见,删除了很多) 在第一个using块中,在删除数据库camsdb之前,我最后一次连接到数据库并执行最后一次查询 查询完成后,代码使用块退出第一个,并应关闭数据库连接 不幸的是,第二个using块(应该删除第一个using块中刚连接到的数据

编辑: @Jeroen Mostert的评论效果很好:向连接字符串添加
Pooling=false
。正如他/她所指出的,我必须多读一些关于这种添加对整体性能的影响的文章

  • 朗:C#
  • 数据库管理系统:Postgres
在下面的代码中,使用两个连续的
块(为了清楚起见,删除了很多)

  • 在第一个
    using
    块中,在删除数据库
    camsdb
    之前,我最后一次连接到数据库并执行最后一次查询
  • 查询完成后,代码使用
  • 块退出第一个
    ,并应关闭数据库连接
    
  • 不幸的是,第二个
    using
    块(应该删除第一个using块中刚连接到的数据库)无法删除数据库。
    postgresception
    表示“还有一个会话正在使用数据库。”
  • 但是,当我使用
    块注释掉第一个
    时,第二个
    使用
    块(履行其职责)会毫无问题地删除数据库。当代码到达相关的大括号时,使用block不是应该关闭连接吗?有没有办法强制垃圾收集器立即清理连接?(欢迎使用任何其他解决方案。)

    M_SqlConn
    类作为一个整体如下(我不想弄乱页面,这就是我最初没有粘贴它的原因):

    我试过@Panagiotis的把戏,但没有成功。将
    if
    块更改为以下内容,但这次程序停止给出“System.NullReferenceException:'对象引用未设置为对象的实例”。”


    您没有为您的sqlConnection调用dispose。 请取消对此的注释

    this.sqlConnection.Dispose();
    
    并删除对方法CloseConnection()的调用

    正如你在这里看到的

    NpgsqlConnection是IDisposable的。当您为它调用Dispose时,它应该运行所有逻辑并关闭连接。编写将调用Close的包装器是不正确的。当你这样做的时候,它会有一个随机的行为


    有一个问题,如果NpgsqlConnection是可以从盒子中IDisposable的,那么您真的需要自己的类,它本质上是一个包装器(或代理)?

    您当然已经知道了,但让我们来解决一些概念

    在C#中使用
    意味着什么?
    这意味着如果类实现了
    IDisposable
    ,则在对象实例生命周期结束时将调用
    Dispose()
    方法

    谁打开和关闭连接? 图书馆做这件事。您只需调用库公开的某个类的实例的某个方法,并希望它能为您完成这项工作

    为什么要保持连接? 大多数情况下,您确实希望在应用程序中重复使用相同的连接,而且大多数情况下,这非常好,因为每个连接都会消耗资源。 这就是为什么我们有连接池

    您能做些什么来缓解您的问题? 您可以按照注释中的建议尝试其他库。 或者查看TemaTre答案她/他看起来对特定的库有很好的了解

    但也要注意,你正在做一些不同寻常的事情。 您确实有两个连接(和两个连接池?)。 一个用于“普通”用户查询数据库。 管理员删除数据库的第二个conn


    我可以建议您首先将数据库置于单用户模式,并确保没有其他连接到它,甚至是应用程序外部的连接。您可以在删除数据库之前使用简单的SQL命令来实现它。

    什么是
    M_SqlConn
    ?那不是标准类型。你能给我看一下这门课吗?您是否编写代码来关闭Dispose方法中的连接?顺便说一句,垃圾收集器不是问题所在。这是您自己的
    Dispose
    逻辑,或者Postgres数据库提供程序将(物理)连接保持在池中。对于特定连接,通常有几种方法可以关闭该功能,但这取决于所使用的连接库。(清除连接池是另一种方法,但这是局部问题的全局解决方案。)
    M_SqlConn
    的任务是在退出using块时关闭连接。不过,很可能不需要这个类。自2006年以来,ADO.NET提供了数据库对象工厂。您甚至可以获得一个已经配置了连接字符串、凭据等的工厂。如果您发布了代码,则根本不调用sqlConnection.Close。无论是否打开,都应该调用sqlConnection.Dispose()。连接的工作是检查和维护其状态。所有教程和示例都显示了如何在
    使用
    块中使用连接,因此,不仅可以在块上使用
    Dispose()
    ,而且它是唯一保证始终工作的方法。我已经粘贴了
    ConnectionClose
    方法。更新我的answer@ssd不要用那种方法。改用
    Dispose()
    。没有理由执行与
    Dispose()
    相同的检查。@PanagiotisKanavos&TemaTre:让我试试。我会让你知道的,不!同样的问题依然存在,尽管我已经对整个
    if
    块进行了注释,并将
    Close
    连接任务完全留给了Npgsql。
    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;
        }
    }
    
    if (this.sqlConnection.State == System.Data.ConnectionState.Open) {
        this.sqlConnection.Dispose(); // exception here
        this.sqlConnection = null;
    }
    
    this.sqlConnection.Dispose();