此 C#/sql 查询代码需要花费大量时间来更新 table

This C# / sql query code takes a lot of time to update the table

任何人都可以帮助提高性能吗?更新 table 需要很多时间。

我正在将序列号从 datagridview 更新到名为 dbo.json

的 table
// UPDATE dbo.json with numbers 
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
    string VAL1;
    string VAL2;

    foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
        if (string.IsNullOrEmpty(row.Cells[5].Value as string))
        {
        }
        else
        {
            for (int i = 0; i <= DgvWhistlSorted.Rows.Count - 2; i++)
            {
                VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
                VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();

                var cnn = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;

                using (var con = new SqlConnection(cnn))
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.CommandType = CommandType.Text;

                    cmd.CommandText = "UPDATE dbo.json SET RowN = @VAL1  WHERE [A-order] = @VAL2";

                    cmd.Parameters.AddWithValue("@VAL1", VAL1);
                    cmd.Parameters.AddWithValue("@VAL2", VAL2);
                            
                    cmd.Connection = con;

                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();
                }
            }
        }
        
        MessageBox.Show("dbo.json is ready");
}

您不应该在如此紧密的循环中创建连接和命令 - 在循环之前创建并打开连接和命令 ONCE,在循环中,仅设置参数值并为每个条目执行查询。

像这样:

// UPDATE dbo.json with numbers 
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
    string VAL1;
    string VAL2;

    // define connection string, query text *ONCE* before the loop  
    string cnn = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
    string updateQuery = "UPDATE dbo.json SET RowN = @VAL1  WHERE [A-order] = @VAL2;";
    
    // create connection and command *ONCE* 
    using (SqlConnection con = new SqlConnection(cnn))
    using (SqlCommand cmd = new SqlCommand(updateQuery, cnn))
    {
        // Define parameters - adapt as needed (don't know the actual datatype they have)
        cmd.Parameters.Add("@VAL1", SqlDbType.VarChar, 100);
        cmd.Parameters.Add("@VAL2", SqlDbType.VarChar, 100);

        // open connection ONCE, for all updates
        con.Open();
        
        foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
        {
            if (!string.IsNullOrEmpty(row.Cells[5].Value as string))
            {
                for (int i = 0; i <= DgvWhistlSorted.Rows.Count - 2; i++)
                {
                    VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
                    VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();

                    // set the values
                    cmd.Parameters["@VAL1"].Value = VAL1;
                    cmd.Parameters["@VAL2"].Value = VAL2;

                    // execute query
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // close connection after all updates are done
        con.Close();
    }

    MessageBox.Show("dbo.json is ready");
}

一个更好的想法是在一个命令中完成,通过在 Table-Value 参数 (TVP):

中传递所有数据

首先创建table类型。我不知道你的数据类型,所以我在这里猜测。确保将类型与现有的 table.

相匹配
CREATE TYPE dbo.OrderJson (
  Order int PRIMARY KEY,
  RowN nvarchar(max) NOT NULL
);

那你就可以一次性全部通过了。您需要创建一个 DataTable 作为参数传递,或者您可以使用现有数据 table.

// UPDATE dbo.json with numbers 
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
    var table = new DataTable {
        Columns = {
            { "Order", typeof(int) },
            { "RowN", typeof(string) },
        },
    };
    foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
        if (!string.IsNullOrEmpty(row.Cells[5].Value as string))
            table.Rows.Add(DgvWhistlSorted.Rows[i].Cells[0].Value, DgvWhistlSorted.Rows[i].Cells[6].Value)

    const string query = @"
UPDATE dbo.json
SET RowN = t.RowN
FROM dbo.json j
JOIN @tmp t ON t.order = j.[A-order];
";
    using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["sql"].ConnectionString))
    using (var cmd = new SqlCommand(query, con))
    {
        cmd.Parameters.Add(new SqlParameter("@tmp", SqlDbType.Structured) { Value = table, TypeName = "dbo.OrderJson" });
        con.Open();
        cmd.ExecuteNonQuery();
    }
        
    MessageBox.Show("dbo.json is ready");
}

创建一次连接...您每次都在通过循环创建一个新的数据库连接!事实上,您不需要每次都创建新的命令对象。您可以重用命令对象,因为参数是相同的。每次通过循环清除参数即可。

也不要在循环中进行网格视图计数,为其设置一个变量。

string query = "UPDATE dbo.json SET RowN = @VAL1  WHERE [A-order] = @VAL2";
int counter = DgvWhistlSorted.Rows.Count - 2;
using (SqlConnection con = new SqlConnection(cnn))
{
      con.Open();
      using(SqlCommand cmd = new SqlCommand(cnn,query))
      {
         cmd.Parameters.Clear();
         //Do your loop in here
         for (int i = 0; i <= counter; i++)
         {
            VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
            VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
            cmd.Parameters.AddWithValue("@VAL1", VAL1);
            cmd.Parameters.AddWithValue("@VAL2", VAL2);                           
                          
            cmd.ExecuteNonQuery();
        }

     }
                
}

我发现最快的方法是将 DATAGRIDVIEW 保存到 SQL table 并使用 - 存储过程 + 更新查询 - 在两个 table 之间继续这个过程 -现在它飞... 谢谢大家