峰峦@叠嶂 2025-07-03 17:08 采纳率: 98%
浏览 14
已结题

查询保存大量数据时,出现超时提示

我的是SQL server2008的,需要查询我们产品追溯码,并保存到数据表,一次约10万条左右,但保存时出现超时提示,若缩减为4万条左右是可以正常保存的,以下是出现的错误提示,及查询保存的代码,请帮我优化一下,能做到即使保存10万条的数据,也不会超时;



```c#
“托管调试助手 "ContextSwitchDeadlock"
  Message=托管调试助手 "ContextSwitchDeadlock":“CLR 无法从 COM 上下文 0x2a04648 转换为 COM 上下文 0x2a04590,这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作。这种情况通常会影响到性能,甚至可能导致应用程序不响应或者使用的内存随时间不断累积。要避免此问题,所有单线程单元(STA)线程都应使用泵式等待基元(如 CoWaitForMultipleHandles),并在运行时间很长的操作过程中定期发送消息”

  if (Compro == "追溯码关联关系")//;
  {
      string Sqldrugquery = @" SELECT d.ID,t.BatchNo,p1.PackCode,   
                  p3.PackCode AS ParentPackCode, --大箱码(LevelNo = 3p3.LevelNo AS LevelNo,1 AS SuNum
                  FROM
                  jishun01.dbo.Task t
                  --获取小盒码(LevelNo = 1)
                  JOIN jishun01_Code.dbo.PackCodeInfo p1
                  ON t.Id = p1.PackageTaskID
                  JOIN jishun01.dbo.w_drugInfo w on t.ProductID = w.ID
                  AND p1.LevelNo = 1
                  JOIN Uploadata.dbo.w_JdrugUpload d on w.NDC = d.NDC and t.BatchNo = d.batchNo1
                  -- 关联中包码(LevelNo = 2)
                  JOIN jishun01_Code.dbo.PackCodeInfo p2
                  ON p1.ParentPackCode = p2.PackCode
                  AND p2.LevelNo = 2

                  -- 关联大箱码(LevelNo = 3)
                  JOIN jishun01_Code.dbo.PackCodeInfo p3
                  ON p2.ParentPackCode = p3.PackCode
                  AND p3.LevelNo = 3
                  WHERE
                  t.ProductDate >= @startdate
                  AND t.ProductDate <= @enddate
                  -- 确保大箱码是最终层级(无父包装)
                  AND p3.ParentPackCode IS NULL;";

      SqlCommand Cmd = new SqlCommand(Sqldrugquery, ConnKcinfo);

      Cmd.Parameters.AddWithValue("@startdate", startdate);
      Cmd.Parameters.AddWithValue("@enddate", enddate);
      Cmd.CommandTimeout = 600;

      SqlDataAdapter sda3 = new SqlDataAdapter(Cmd);

      dt.Rows.Clear();
      dt.Columns.Clear();
      dataGridView1.Columns.Clear();

      sda3.Fill(dt);

      // 批量插入
      using (SqlConnection ConnMesInfo = new SqlConnection(Conn1))
      {
          ConnMesInfo.Open();
          using (SqlBulkCopy bulkCopy = new SqlBulkCopy(ConnMesInfo, SqlBulkCopyOptions.TableLock, null))
          {
              bulkCopy.DestinationTableName = "w_JTcodeUpload";
              bulkCopy.BatchSize = 5000;
              bulkCopy.BulkCopyTimeout = 600;

              // 显式映射列(跳过 id 字段)
              bulkCopy.ColumnMappings.Add("ID", "batchNo");
              bulkCopy.ColumnMappings.Add("ParentPackCode", "TlevelCode");
              bulkCopy.ColumnMappings.Add("PackCode", "FlevelCode");
              bulkCopy.ColumnMappings.Add("LevelNo", "PackLevel");
              bulkCopy.ColumnMappings.Add("SuNum", "SuNum");

              bulkCopy.WriteToServer(dt);

              // 添加提示(在插入完成后立即提示)
              MessageBox.Show($"数据批量插入成功!共插入 {dt.Rows.Count} 条记录",
                              "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

          }
      }

      //dataGridView1.DataSource = dt;

      dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;


  }

```

  • 写回答

7条回答 默认 最新

  • 阿里嘎多学长 2025-07-03 17:08
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    查询保存大量数据时,出现超时提示

    你遇到的问题是SQL Server 2008中查询大量数据时出现超时提示,导致保存数据失败。你的情况是查询10万条左右的数据,然后保存到数据表中。

    错误提示可能是超时错误,例如:

    Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

    解决方案:

    1. 优化查询语句:检查你的查询语句是否可以优化,例如使用索引、减少JOIN操作、使用子查询等。
    2. 分批处理:将数据分批处理,可以使用C#中的SqlDataReader对象来读取数据,然后将数据分批保存到数据表中。
    3. 使用事务:使用事务来保存数据,可以确保数据的完整性和一致性。
    4. 调整超时时间:可以在SQL Server中调整超时时间,例如在连接字符串中添加Connect Timeout参数。

    以下是一个使用SqlDataReader对象分批处理数据的示例代码:

    using System;
    using System.Data;
    using System.Data.SqlClient;
    
    // 连接字符串
    string connectionString = "Data Source=your_server;Initial Catalog=your_database;User ID=your_username;Password=your_password;";
    
    // 查询语句
    string query = "SELECT * FROM your_table";
    
    // 创建连接对象
    SqlConnection connection = new SqlConnection(connectionString);
    connection.Open();
    
    // 创建命令对象
    SqlCommand command = new SqlCommand(query, connection);
    
    // 创建读取器对象
    SqlDataReader reader = command.ExecuteReader();
    
    // 分批处理数据
    int batchSize = 1000;
    int count = 0;
    while (reader.Read())
    {
        // 处理数据
        // ...
    
        // 将数据保存到数据表中
        SqlCommand insertCommand = new SqlCommand("INSERT INTO your_table (column1, column2, ...) VALUES (@column1, @column2, ...)", connection);
        insertCommand.Parameters.AddWithValue("@column1", reader["column1"]);
        insertCommand.Parameters.AddWithValue("@column2", reader["column2"]);
        // ...
        insertCommand.ExecuteNonQuery();
    
        // 计数器
        count++;
        if (count >= batchSize)
        {
            // 保存数据
            connection.SaveChanges();
            count = 0;
        }
    }
    
    // 保存最后一批数据
    if (count > 0)
    {
        connection.SaveChanges();
    }
    
    // 关闭连接
    connection.Close();
    

    这个示例代码中,我们使用SqlDataReader对象读取数据,然后将数据分批处理,使用SqlCommand对象将数据保存到数据表中。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 系统已结题 9月5日
  • 已采纳回答 8月28日
  • 创建了问题 7月3日