SqlCommand 正确关闭连接

SqlCommand closing connections properly

我最近一直在做一个旧项目。我在项目中发现以前的同事已经创建了一些用于打开与数据库的连接的常用方法。但是我怀疑这个过程是否真的在查询完成后通过 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);
    } 
}

您认为这个过程会正确释放所有连接吗?

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

代码不安全。 Disposing/closing reader 不会自动关闭连接,因为您可能希望在同一个连接上执行多个命令。即使您使用 the override 确实 关闭连接,在您进入 using 块之前可能发生的异常将使连接保持打开状态。

典型的方式是将连接、命令和reader包装在using语句中:

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

不,您的代码没有像其他答案中确认的那样正确释放所有连接。 鉴于修改旧程序可能是一场噩梦,我建议采用这样的方法

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")));
        }
    }
}