C# Write Async 一个特定的数据大小

C# Write Async a specific data size

我在 C# 中有一个 API 来自数据库的 returns 数据和一个在 table.

中绘制该数据的前端

我的方法是使用 sqlReader 从数据库中读取数据,遍历此 reader 将每个结果添加到列表中,然后 return 该列表到前端。

看起来很简单,直到我收到大量查询数据。我的解决方案是逐块 return 这个数据块,但我坚持使用它,这是我正在使用的代码:

 var sqlCommand = db.InitializeSqlCommand(query);
                try
                {
                    using (var reader = sqlCommand.ExecuteReader())
                    {
                        var results = new List<List<string>>();
                        var headers = new List<string>();
                        var rows = new List<string>();
                        for (var i = 0; i < reader.FieldCount; i++)
                        {
                            headers.Add(reader.GetName(i));
                        }
                        results.Add(headers);
                        while (reader.Read())
                        {
                            for (var i = 0; i < reader.FieldCount; i++)
                            {
                                rows.Add((reader[reader.GetName(i)]).ToString());
                            }
                            results.Add(rows);
                            var str = JsonConvert.SerializeObject(results);
                            var buffer = Encoding.UTF8.GetBytes(str);

                            //Thread.Sleep(1000);
                            await outputStream.WriteAsync(buffer, 0, buffer.Length);
                            rows.Clear();
                            results.Clear();
                            outputStream.Flush();

                        }
                    }
                }
                catch (HttpException ex)
                {
                    if (ex.ErrorCode == -2147023667) // The remote host closed the connection. 
                    {
                    }
                }
                finally
                {
                    outputStream.Close();
                    db.Dispose();
                }

有了这个,我可以一个一个地 return 数据(用 Thread.sleep 测试过),但我不知道如何 return 一个特定的数量,说200条数据还是1000条数据,真的应该无所谓。

知道如何进行吗? 提前致谢。 梅塞.

我认为控制查询是更好的方法,因为这是将从数据库中获取的内容。您可以为每个后续 运行 增加 OFFSET。示例 - 在 ORDER BY 子句之后添加 OFFSET 200 ROWS FETCH NEXT 200 ROWS ONLY 以跳过 200 行并获取接下来的 200 行。

但是,既然您已经提到您无法控制查询,那么您可以执行类似这样的操作来过滤我们的结果。这里的关键技巧是使用 reader.AsEnumerable.Skip(200).Take(200) 来选择要处理的行。在每次迭代中将输入更新为 Skip() 以相应地处理数据。

// Offset variable will decide how many rows to skip, the outer while loop can be
// used to determine if more data is present and increment offset by 200 or any
// other value as required. Offset -> 0, 200, 400, 600, etc.. until data is present

bool hasMoreData = true;
int offset = 0;
while(hasMoreData)
{
    // SQL Data reader and other important operations
    foreach(var row in reader.AsEnumerable.Skip(offset).Take(200)) 
    { 
        // Processing operations
    }
    // Check to ensure there are more rows
    if(no more rows)
        hasMoreData = false;
    offset += 200;
}

另一件要记住的事情是,当您批量提取数据时,查询将执行多次,如果在此期间添加或删除了新记录,则批处理将无法正常运行。要解决这个问题,您可以做两件事:

  • 使用已提取记录的唯一 ID 验证每条记录的唯一 ID,以确保不会拉取同一条记录两次(由于记录 addition/deletion 导致的极端情况)
  • 为您的偏移量添加一个缓冲区,例如
    • Skip(0).Take(100) // 提取 0 - 100 条记录
    • Skip(90).Take(100) // 提取 90 - 190 条记录(重叠 10 条以满足 additions/deletions)
    • Skip(180).Take(100) // 提取 180 - 280 条记录(重叠 10 条以满足 additions/deletions)
    • 等等...

希望对您有所帮助!