【问题标题】:Does for loop open and close a database connection on each iteration?for 循环是否在每次迭代时打开和关闭数据库连接?
【发布时间】:2014-09-20 05:48:26
【问题描述】:

我正在帮助调试一些代码并有以下 for 循环。它是否在每次迭代时打开和关闭与数据库的连接?

for (int i = 0; i < count; i++)
{
    int num = dataTable.Rows[i]["Location_Id"]
    database.ProcessAlerts("spProcessAlerts", num)
}

从数据库类,这里是相关部分:

public bool GetConnection()
{
    try
    {
        GeneralLib.GetIniSettings();
        string connectionStrings = GeneralLib.Settings.ConnectionStrings;
        Database.conn = new SqlConnection(connectionStrings);
        Database.conn.Open();
    }
...
public void ProcessAlerts(string ProcedureName, int nByLocationId)
{
    try
{
    if (this.GetConnection())
    {
        SqlCommand sqlCommand = new SqlCommand(ProcedureName, Database.conn);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        SqlParameter sqlParameter = sqlCommand.Parameters.Add("@ByLocation_Id", SqlDbType.Int);
        sqlParameter.Value = nByLocationId;
        sqlCommand.ExecuteNonQuery();
        this.CloseConnection();
    }
}

我的直觉让我相信 for 循环在每次迭代时都会打开/关闭,但由于我根本不使用 .net,所以我真的不知道。我对此进行了大量搜索,但没有找到满意的答案(如Execution Time Slower with each Iteration of the same SPROCKeep Sql Connection open for iterating many requests? Or close each step?Opening and closing database connection for each queryC# SQLConnection pooling)。一些帖子说在需要时打开连接并立即关闭它,而另一些帖子则说如果您使用连接池,连接并没有真正关闭,它只是不可用。我不完全明白这一点。

基本上,这段代码应该处理信息以便可以发送警报,而我们最近在此过程中遇到了很大的时间延迟。从日志中,我可以看到 for 循环何时开始/停止,有时循环数千条记录需要几个小时。也可能是 spProcessAlerts 需要花费大量时间来运行某些行,所以我也在研究其中发生的情况。

【问题讨论】:

  • 您是否尝试过使用 SQL Profiler 进行验证?代码读起来就像每次都会打开一个新连接
  • 看起来确实如此。您可能想为该连接尝试某种单例模式goo.gl/kmlo 实现
  • 打开几千个连接不需要几个小时。在别处寻找问题。你不怀疑这些查询吗?
  • 这个问题是由“this.CloseConnection();”引起的在您的 ProcessAlerts 方法上。每次调用它时都会关闭连接。比下一个呼叫打开新连接。
  • @GR 特使 +1000。简介,简介,简介。对 SO 的课程提问要容易得多。

标签: c# .net sql-server performance


【解决方案1】:

您拥有代码的方式,是的,看起来您每次都在打开一个新连接,但您不必那样做。

我会将您的 GetConnection 改造成 OpenConnection 和 CheckConnection,其中 OpenConnection 设置一个布尔值,并且 CheckConnection 仅在该布尔值为 false 时调用 OpenConnection。然后我会在你的 for 循环上方调用 OpenConnection,(我也会在它下面建立一个紧密的连接)

【讨论】:

  • 什么是连接关闭。我最好在打开之前检查连接以确保它仍然是有效的连接
  • 我建议您仔细阅读Jon's examples,而不是临时单身人士
【解决方案2】:

是的……也不是。

ADO.Net 使用 Connection Pooling. 因此,当您反复调用 Connection.Open()Connection.Close() 时,ADO.Net可能只是将相同的现有、已经打开的连接交还给您。

不过,我的偏好仍然是在循环之外抽象出这种东西。

【讨论】:

    【解决方案3】:

    如果你想要像管道这样的单一连接,你可以像这样改变你的代码:

    using(var connection= GetConnectionX()){
    connection.Open();
    for (int i = 0; i < count; i++)
    {
       int num = dataTable.Rows[i]["Location_Id"]
       database.ProcessAlerts("spProcessAlerts", num, connection)
    }
    }
    
     public SqlServerConnection GetConnectionX()
     {
    
        GeneralLib.GetIniSettings();
        string connectionStrings = GeneralLib.Settings.ConnectionStrings;
        return  new SqlConnection(connectionStrings);
    
     }
    
    
    
      public void ProcessAlerts(string ProcedureName, int nByLocationId , SqlServerConnection connection)
     {
       try
       {
    
        SqlCommand sqlCommand = new SqlCommand(ProcedureName, connection);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        SqlParameter sqlParameter = sqlCommand.Parameters.Add("@ByLocation_Id", SqlDbType.Int);
        sqlParameter.Value = nByLocationId;
        sqlCommand.ExecuteNonQuery();
    }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多