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

如何在SqlDataReader打开状态下执行SQL查询?

解决SqlDataReader打开时执行SQL查询的问题

首先,你遇到的System.InvalidOperationException错误,核心原因是SQL Server默认不允许在同一个数据库连接上同时运行一个打开的DataReader和另一个SQL命令。下面给你几种可行的解决方案,以及解答你的其他疑问:

方案1:启用MultipleActiveResultSets (MARS)

这是最简单的解决方式,只需要修改你的连接字符串,添加MultipleActiveResultSets=True配置,这样同一个连接就可以同时处理DataReader和其他SQL命令了。

修改后的连接字符串示例:

var builder = new SqlConnectionStringBuilder();
builder.ConnectionString = "你的原有连接字符串";
builder.MultipleActiveResultSets = true; // 启用MARS

using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
    // 你的原有代码逻辑
}

方案2:先读取所有数据到List,再关闭DataReader执行插入

既然你需要把SqlDataReader返回的值存储到List中,你可以先一次性把所有数据加载到内存的List里,然后关闭DataReader,再执行循环插入操作。这样就不会占用连接,避免冲突:

using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
    connection.Open();
    Console.WriteLine("\n List of Bracelets:");
    Console.WriteLine("=========================================\n");

    List<object> al = new List<object>();
    string selectQuery = "你的查询语句"; // 补充你的查询命令
    using (SqlCommand command = new SqlCommand(selectQuery, connection))
    {
        // 先读取所有数据到List
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                Console.WriteLine(String.Format(" Id Bracelet :{0} | Id Client: {1} | First Name: {2} | Last Name: {3}", 
                    reader["IdBracelet"], reader["IdClient"], reader["FirstName"], reader["LastName"]));
                al.Add(reader["IdBracelet"]);
            }
        } // reader在这里自动关闭
    }

    // 现在执行循环插入操作
    while (true)
    {
        Y.Function();
        string strQueryInsert = "Insert into TableZ(xxx, xx, xxxx, xxxxx, xxxxxx) values (@xxx, @xx, @xxxx, @xxxxx, @xxxxxx)";
        using (SqlCommand cmd = new SqlCommand(strQueryInsert, connection))
        {
            cmd.Parameters.AddWithValue("@xxx", xxx);
            cmd.Parameters.AddWithValue("@xx", xx);
            cmd.Parameters.AddWithValue("@xxxx", xxxx);
            cmd.Parameters.AddWithValue("@xxxxx", xxxxx);
            cmd.Parameters.AddWithValue("@xxxxxx", xxxxxx);
            cmd.ExecuteNonQuery();
        }
        Thread.Sleep(5000);
    }
}

方案3:使用独立的第二个数据库连接

如果不想启用MARS,也不想提前加载所有数据,你可以在插入操作中新建一个独立的SqlConnection,这样两个连接互不干扰:

using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
    connection.Open();
    Console.WriteLine("\n List of Bracelets:");
    Console.WriteLine("=========================================\n");

    List<object> al = new List<object>();
    string selectQuery = "你的查询语句";
    using (SqlCommand command = new SqlCommand(selectQuery, connection))
    {
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                Console.WriteLine(String.Format(" Id Bracelet :{0} | Id Client: {1} | First Name: {2} | Last Name: {3}", 
                    reader["IdBracelet"], reader["IdClient"], reader["FirstName"], reader["LastName"]));
                al.Add(reader["IdBracelet"]);

                // 这里使用新的连接执行插入
                using (SqlConnection insertConn = new SqlConnection(builder.ConnectionString))
                {
                    insertConn.Open();
                    Y.Function();
                    string strQueryInsert = "Insert into TableZ(xxx, xx, xxxx, xxxxx, xxxxxx) values (@xxx, @xx, @xxxx, @xxxxx, @xxxxxx)";
                    using (SqlCommand cmd = new SqlCommand(strQueryInsert, insertConn))
                    {
                        cmd.Parameters.AddWithValue("@xxx", xxx);
                        cmd.Parameters.AddWithValue("@xx", xx);
                        cmd.Parameters.AddWithValue("@xxxx", xxxx);
                        cmd.Parameters.AddWithValue("@xxxxx", xxxxx);
                        cmd.Parameters.AddWithValue("@xxxxxx", xxxxxx);
                        cmd.ExecuteNonQuery();
                    }
                }
                Thread.Sleep(5000);
            }
        }
    }
}

你的其他疑问解答

1. 插入语法是否正确?

你的插入语法是正确的,使用参数化查询的方式可以有效避免SQL注入,只要确保:

  • 参数名@xxx等和SQL语句中的占位符完全对应
  • 参数值的类型和TableZ表中对应字段的数据类型匹配

2. 是否需要打开第二个连接?

这取决于你选择的解决方案:

  • 如果启用了MARS,不需要第二个连接,同一个连接可以同时处理DataReader和插入命令
  • 如果选择提前加载数据到List,也不需要第二个连接,关闭DataReader后复用原连接即可
  • 如果要在DataReader打开的同时执行插入,又不想启用MARS,就需要第二个独立的连接

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:12:00