【问题标题】:SQL connection performance questionSQL连接性能问题
【发布时间】:2011-03-26 23:21:23
【问题描述】:

使用 C#、Visual Studio 2008、SQL Server 2000(和 2008)

我在我的 Web 应用程序中使用 DataLayer 类进行 SQL 调用:

DataLayer 中包含应用程序的所有 SQL 调用,所有 SQL 活动都发生在该类中。

例如:

protected void UpdatePeople(int iPeopleID, string Lastname......)
{
    InitCmd("sUpdatePeople");
    c_objSQLCmd.Parameters.Add(new SqlParameter("@PeopleID", iPeopleID));
    c_objSQLCmd.Parameters.Add(new SqlParameter("@LastName", szLastName));
    CmdExecuteNonQuery();
}

然后,我有执行 SQL 工作的辅助对象:

    private void InitCmdSP(string szStoredProc)
    {
        c_objSQLCmd.Parameters.Clear();
        c_objSQLCmd.CommandType = CommandType.StoredProcedure;
        c_objSQLCmd.CommandText = szStoredProc;
    }
    private int CmdExecuteNonQuery()
    {
        int iReturn = 0;
        if (c_objSQLConn.State != ConnectionState.Open)
            c_objSQLConn.Open();
        iReturn = c_objSQLCmd.ExecuteNonQuery();
        c_objSQLConn.Close();
        return iReturn;
    }

我还有返回 DataTable 或 DataSet 以及 ExecuteScalar 并根据需要返回 int、string 等的辅助对象。

我的问题是,每次打开/关闭 SQL 连接会对性能造成什么影响?

到目前为止,这些应用程序的用户通常少于 600-700 个,而且同时用户数量也不多,因此用户感知的性能可能不是真正的问题。我只是在尝试考虑最佳做法。

谢谢, 约翰

【问题讨论】:

标签: c# sql-server


【解决方案1】:

不多。 Your connections are pooled by default 以避免真正的打开/关闭开销。

您可以通过运行 SQL Profiler 来测试池:您会看到 sp_reset_connection 调用

【讨论】:

    【解决方案2】:

    每次关闭连接可能对性能几乎没有影响。

    Sql Server ADO.NET 提供程序会自动为您的应用程序使用连接池(除非您明确告诉它不要这样做)。

    但使用任何实现IDisposable(包括SqlConnectionSqlCommand)的最佳实践是将项目包装在using 块中,如下所示:

    using(var connection = new SqlConnection(...))
    {
        using(var command = connection.CreateCommand())
        {
            // Do something with the command.
        }
    }
    

    这可确保尽早释放任何非托管资源,并且重要的是可以抵抗异常代码路径。上面的代码是语法糖:

    SqlConnection connection;
    
    try
    {
        connection = new SqlConnection(...);
    
        SqlCommand command;
    
        try
        {
            command = connection.CreateCommand();
    
            // Do something with the command.
        }
        finally
        {
            if(command != null)
            {
                command.Dispose();
            }
        }
    }
    finally
    {
        if(connection != null)
        {
            connection.Dispose();
        }
    }
    

    所以基本上,using 很棒。

    【讨论】:

    • @Xcaliburp 感谢您的使用建议;但是,我不确定如何使用我使用的辅助对象来实现它。我如何将现有命令对象 (c_objSQLCmd) 与提示中的“command = connection.CreateCommand()”相关联?谢谢,约翰。
    • 经过进一步思考,我假设我可以在 using 语句中使用现有对象。 IE。使用 (c_objSQLcmd),对吗?
    • @John - 不,您不能在 using 语句中重用对象。 using 语句将调用 dispose 并且在对象的生命周期中只能发生一次。我不确定通过多个方法共享命令对象可以获得什么好处。每次需要时,我都会创建并处理一个新的。或者我将它作为参数传递(依赖注入) - 在这种情况下,调用堆栈中的使用会更高。
    • @John - 你可以保留现有的模式,但你的类应该实现 idisposable 并调用 dispose 那里的命令。那么你应该在调用你的类时使用 using 语句。
    • 我这样做有几个原因,其中一个是为了简化代码的可读性,另一个是将所有 SQL 逻辑保存在一个位置。对我来说,将本质上完全相同的代码放在调用执行 SP 的每个方法中似乎没有意义。所以,在每个方法中:我调用初始化命令对象的方法;将 SqlParameters 附加到命令对象;并且,调用方法来执行命令对象并返回所需的任何类型(int、string、datatable、dataset)。
    【解决方案3】:

    您可以通过根据访问您的 Web 应用程序的请求数设置 minimum PoolSize 来考虑使用连接池。此外,您可以考虑将所有连接逻辑包装在 using 语句中,以确保清理所有连接。 如:

    using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();      
        }
    

    这是一个article,可帮助您开始使用连接池。既然你有一个网络应用,你也可以考虑Unit of work pattern

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-29
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 2012-02-12
      • 1970-01-01
      相关资源
      最近更新 更多