You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#查询股东余额后循环更新时出现连接未关闭错误求助

问题分析与修复

错误根源

你的代码中,SqlDataReader在读取数据时会独占数据库连接,此时在同一个连接上执行ExecuteNonQuery(更新操作)会触发连接冲突,导致“连接未关闭”类错误。因为DataReader打开期间,连接被锁定用于读取,无法同时执行其他命令。

另外原代码还有两个潜在问题:

  1. 未使用using语句管理连接、命令和DataReader,一旦出现异常,连接可能无法正常关闭,导致连接泄漏。
  2. 判断rdr["current_balance"] != null无效,数据库中的NULL值在DataReader中会以DBNull.Value形式存在,应该用rdr.IsDBNull()判断。

最优修复方案:单条SQL直接更新

不需要逐行读取数据再更新,直接用SQL语句在数据库层面完成计算和更新,性能更高且完全避免连接冲突:

try
{
    // 使用using自动释放连接,无需手动Close
    using (var con = new SqlConnection(constr))
    {
        con.Open();
        // 直接通过SQL计算新余额,同时更新两个字段
        string updateSql = @"UPDATE shareholders_term 
                             SET profit_percentage = @profitPercentage,
                                 current_balance = current_balance * (1 + @profitPercentage / 100)
                             WHERE current_balance IS NOT NULL";

        var cmd = new SqlCommand(updateSql, con);
        cmd.Parameters.AddWithValue("@profitPercentage", profitpercentage);

        int updatedCount = cmd.ExecuteNonQuery();
        lblupdatecounter.Text = updatedCount + " - Shareholders updated.";
        MessageBox.Show("Profit added to shareholders");
    }
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

若需保留逐行处理逻辑(如额外业务)

如果必须逐行处理(比如有其他业务逻辑要执行),可以先把数据读到内存,再关闭DataReader后进行更新:

try
{
    // 1. 先读取所有需要更新的数据到内存
    var shareholderList = new List<(int ShareholderId, decimal CurrentBalance)>();
    using (var con = new SqlConnection(constr))
    {
        con.Open();
        string selectSql = "SELECT shareholder_id, current_balance FROM shareholders_term WHERE current_balance IS NOT NULL";
        using (var cmd = new SqlCommand(selectSql, con))
        using (var rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {
                int id = Convert.ToInt32(rdr["shareholder_id"]);
                decimal balance = Convert.ToDecimal(rdr["current_balance"]);
                shareholderList.Add((id, balance));
            }
        } // DataReader自动关闭
    } // 连接自动关闭

    // 2. 逐行更新数据
    int num = 0;
    using (var con = new SqlConnection(constr))
    {
        con.Open();
        string updateSql = @"UPDATE shareholders_term 
                             SET profit_percentage = @percentage,
                                 current_balance = @newBalance 
                             WHERE shareholder_id = @shareholderId";

        foreach (var shareholder in shareholderList)
        {
            num++;
            decimal profitAmount = shareholder.CurrentBalance * profitpercentage / 100;
            decimal newBalance = shareholder.CurrentBalance + profitAmount;

            using (var cmd = new SqlCommand(updateSql, con))
            {
                cmd.Parameters.AddWithValue("@percentage", profitpercentage);
                cmd.Parameters.AddWithValue("@newBalance", newBalance);
                cmd.Parameters.AddWithValue("@shareholderId", shareholder.ShareholderId);
                cmd.ExecuteNonQuery();
            }

            lblupdatecounter.Text = num + " - Shareholders updated.";
        }
    }

    MessageBox.Show("Profit added to shareholders");
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

内容的提问来源于stack exchange,提问作者user3387814

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:52:06