C# sql 为每个查询创建一个连接并打开和关闭

C# sql create one connection and open and close for each query

我最近继承了一个 C# Web 应用程序,它为每个查询创建一个新连接,如下所示:

public class QueryForm
{
    public bool getStudents()
    {
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
        conn.Open();
        //commands
        conn.Close();
    }

    protected void getProfessors()
    {
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
        conn.Open();
        //Commands
        conn.Close();
    }


    protected void getProfessors()
    {
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
        conn.Open();
        //Commands
        conn.Close();
    }
}

我知道这通常是最好的方法,但是可以接受还是 "best practice" 让构造函数创建连接对象,然后让每个 method/Query 打开然后关闭这样的连接:

public class QueryForm
{
    SqlConnection conn;

    public QueryForm()
    {
        conn = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
    }

    public bool getStudents()
    {
        conn.Open();
        //commands
        conn.Close();
    }

    protected void getProfessors()
    {
        conn.Open();
        //Commands
        conn.Close();
    }

    protected void getCourses()
    {
        conn.Open();
        //Commands
        conn.Close();
    }
}

我更喜欢第二种方式,因为它不会创建多个连接对象。但是,如果我要使方法和 class 静态化,第一种方法也更可取。

其中任何一个都可以接受。 SqlConnection 使用连接池,因此它不会对性能产生太大影响。拥有多个 SqlConnection 对象不会造成任何伤害。这归结为偏好。

如果您将连接保留在方法中,我建议将命令封装在 using 语句中,例如:

using (SqlConnection conn = new SqlConnection(...))
{
    conn.Open();
    //commands
    conn.Close();
}

这确保正确处理连接。

保持连接打开的时间尽可能短很重要。 SQL 连接正在使用 connection pool,因此打开连接实际上会在后台重用连接。 如果你保持连接打开,你有 运行 错误的风险: 'Parallel transactions are not supported' 如果你使用方法 BeginTransaction.

这是一个可能有大量连接的网络应用程序, 让连接对象保持打开状态的时间更长会使您面临耗尽连接池并出现以下情况的风险:'The timeout period elapsed prior to obtaining a connection from the pool' 错误。

此外,即使抛出异常,您也必须确保连接已关闭。

这应该使用像这样的 using 块来完成:

using (SqlConnection conn = new SqlConnection(...))
{
    conn.Open();
    //commands
}

自从退出 'using' 块后,对已使用的对象调用 .Dispose()。

或使用 try / catch / finally 块,例如:

SqlConnection conn = null;

try
{
    conn = new SqlConnection(...);    
    conn.Open();
    //commands
}
catch(Exception ex)
{
    ...
}
finally
{
    if(conn != null)
        conn.Close();
}