简体   繁体   English

SqlCommand正确关闭连接

[英]SqlCommand closing connections properly

I have been working on an old project recently. 我最近一直在做一个旧项目。 I found in the project that previous colleagues have created some common methods to use for to open connection to database. 我在该项目中发现,以前的同事已经创建了一些常用方法来打开与数据库的连接。 But I have a doubt about the process whether it really handles connection by IDispose once the query completes. 但是我对查询完成后是否真正通过IDispose处理连接的过程感到怀疑。

Here is the methods: 方法如下:

Connect database. 连接数据库。

/// <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;
}

Then we use GetDataReader as below 然后我们使用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);
    } 
}

Do you think this process would release all the connection correctly? 您是否认为此过程可以正确释放所有连接?

The code isn't safe. 该代码不安全。 Disposing/closing the reader doesn't automatically close the connection, as you may want to execute multiple commands on the same connection. 布置/关闭阅读器不会自动关闭连接,因为您可能希望在同一连接上执行多个命令。 Even if you use the override that does close the connection, exceptions that may occur before you enter the using block will leave the connection open. 即使您使用确实会关闭连接的替代 ,在进入using块之前可能发生的异常也会使连接保持打开状态。

The typical way is to wrap the connection, command and reader in using statements: 典型的方法是在using语句中包装连接,命令和读取器:

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

SqlConnection also implements IDisposable interface, so you have to close the connection too. SqlConnection还实现了IDisposable接口,因此您也必须关闭连接。 So you should also wrap the connection in using block. 因此,您还应该将连接包装在using块中。

No, your code doesn't release all the connections correctly as they have confirmed in other answers. 不,您的代码无法正确释放所有连接,如在其他答案中已确认的那样。 Whereas modify an old program can be a nightmare I suggest an approach like this 尽管修改旧程序可能是一场噩梦,但我建议采用这种方法

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM