SqlCommand正确关闭连接

本文关键字:连接 SqlCommand | 更新日期: 2023-09-27 17:55:06

我最近一直在做一个老项目。我在项目中发现,以前的同事已经创建了一些常用的方法来打开数据库连接。但是我对这个进程有疑问,一旦查询完成,它是否真的通过IDispose处理连接。

方法如下:

连接数据库。

/// <summary>
///     This method creates a connection object to the database.
/// </summary>
/// <returns>a new SQL Connection</returns>
public SqlConnection ConnectDB()
{
    var db = new SqlConnection(ConnectionString);
    db.Open();
    return db;
} 
public SqlDataReader GetDataReader(SqlCommand query)
{
    var db = ConnectDB();
    query.Connection = db;
    var reader = query.ExecuteReader();
    return reader;
}

然后使用GetDataReader,如下所示

var queryProduct= new SqlCommand
{
    CommandText = "SELECT DISTINCT ProductName FROM Products"
};   
using (var reader = Interaction.GetDataReader(queryProduct))
{
    while (reader.Read())
    {
         var b = new Product
         {
              ProductName = reader.GetString(reader.GetOrdinal("ProductName"))
         };
         products.Add(b);
    } 
}

你认为这个进程会正确释放所有的连接吗?

SqlCommand正确关闭连接

代码不安全。处理/关闭读取器不会自动关闭连接,因为您可能希望在同一连接上执行多个命令。即使您使用的覆盖关闭连接,在您进入using块之前可能发生的异常也会使连接保持打开状态。

典型的方法是将连接、命令和读取器封装在using语句中:

using(var con=new SqlConnection(connectionString))
using(var command=new SqlCommand(sql,con))
{
    con.Open();
    using(var reader=command.ExecuteReader())
    {
    ....
    }
}

SqlConnection也实现了IDisposable接口,所以你也必须关闭连接。因此,您还应该在using块中包装连接。

不,你的代码没有正确释放所有的连接,因为他们已经在其他答案中确认。鉴于修改旧程序可能是一场噩梦,我建议采用如下方法

class Program
{
    static IEnumerable<SqlDataReader> InteractionGetData(string query)
    {
        using (var connection = new SqlConnection(@"Data Source=localhost;Integrated Security=SSPI;"))
        {
            connection.Open();
            using (var command = new SqlCommand(query, connection))
            {
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        yield return reader;
                    }
                }
            }
        }
    }
    static void Main(string[] args)
    {
        foreach (var reader in InteractionGetData("SELECT DISTINCT ProductName FROM Products"))
        {
            Console.WriteLine(reader.GetString(reader.GetOrdinal("ProductName")));
        }
    }
}