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)
- 等等...
希望对您有所帮助!
我在 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)- 等等...
希望对您有所帮助!