【问题标题】:Is the correct way to leave no unclosed connections?不留下未关闭的连接的正确方法是什么?
【发布时间】:2016-06-30 04:42:21
【问题描述】:

我正在尝试调试我的源代码

异常:System.InvalidOperationException

消息:内部 .Net Framework 数据提供程序错误 1。

堆栈跟踪:在 System.Data.ProviderBase.DbConnectionInternal.PrePush(对象 预期所有者)在 System.Data.ProviderBase.DbConnectionPool.PutObject(DbConnectionInternal obj,对象拥有对象)在 System.Data.ProviderBase.DbConnectionInternal.CloseConnection(DbConnection 拥有对象,DbConnectionFactory 连接工厂)在 System.Data.SqlClient.SqlConnection.CloseInnerConnection() 在 System.Data.SqlClient.SqlConnection.Close() 在 System.Data.SqlClient.SqlConnection.Dispose(布尔处理)在 System.ComponentModel.Component.Dispose()

我在日志文件中看到的并且我认为会导致 502 错误的错误。我与数据库的所有交互(我正在尝试以最老派的方式进行此操作)就像

    public List<VersionInfo> GetAllVersions ( )
    {
        List<VersionInfo> Versions = new List<VersionInfo>();
        using (SqlConnection con = new SqlConnection(SurveyDbModel._conn))
        {
            con.Open();
            using (SqlCommand cmd = new SqlCommand("GetAllVersions",con))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                using (SqlDataReader dataReader = cmd.ExecuteReader())
                {
                    while (dataReader.Read())
                    {
                        Versions.Add(new VersionInfo
                        {
                            Id = !dataReader.IsDBNull(0) ? dataReader.GetInt32(0) : default(int),
                            Title = !dataReader.IsDBNull(1) ? dataReader.GetString(1) : String.Empty
                        });
                    }
                }
            }
            con.Close();
        }
        return Versions;
    }

我在做usings 对吗?有什么嵌套错误吗?

【问题讨论】:

  • 为什么要关闭连接?我想在using 语句连接关闭之后。
  • 你能链接配置文件吗?也许您的提供程序/连接字符串有问题
  • 去掉那个多余的con.Close();,看看它是否仍然存在。
  • @ragerory 所以我不应该在using (SqlConnection con = new SqlConnection(SurveyDbModel._conn)) 中使用con.Close()?是多余的吗?
  • 连接被释放时会关闭,是的。

标签: c# sql asp.net tsql


【解决方案1】:

您收到的错误不是因为无效的连接处理。通过使用 using() { } 范围,您可以很好地实现它,因为连接将在离开范围时自动释放。但是,GetAllVersions 不是一个有效的操作,可能是因为过程逻辑有问题,也可能是因为它不存在,这就是错误的原因。

如果您实际上有一个以这种方式命名的存储过程(这不是好的做法),您应该在它前面加上 exec,例如:

exec GetAllVersions

但是,您应该重命名它以遵循通用准则: 执行 usp_GetAllVersions

或类似的,请参阅https://www.mssqltips.com/sqlservertutorial/169/naming-conventions-for-sql-server-stored-procedures/ 以获取有关良好命名的示例。

编辑 1: 我建议您将存储过程与您的问题一起发布,或者您检查存储过程是否可在用户会话中运行。我的钱是在那上面的。

【讨论】:

  • 调用存储过程时,只需提供过程名称作为命令文本,不包括“exec”。
  • 只有当存储过程是批处理中的第一个语句时才如此,这就是为什么总是在存储过程前加上 exec 是一个好习惯。
  • 如果您在命令文本中的存储过程名称前键入“exec”,在使用命令类型存储过程时,它将查找名为 exec 的过程。您会收到如下消息:Could not find stored procedure 'exec