答案是 CommandBehavior.SequentialAccess 实现流式读取,需按列顺序访问数据,适用于大字段处理,通过逐步读取避免内存溢出,常用于 SqlDataReader 配合 GetBytes 或 GetTextReader 流式读取二进制或文本数据。
数据库的平面缓冲区模式(Flat Buffer Mode)并不是一个标准的数据库术语,更准确地说,这个概念可能源于对“缓冲区”或“数据读取方式”的误解。你可能实际想了解的是 流式读取模式 或 顺序访问模式,尤其是在使用 ADO.NET 时通过 DataReader 实现的高效只进只读数据访问方式。
在 C# 中,最常见的实现方式是使用 SqlDataReader 配合 CommandBehavior.SequentialAccess,这种组合常被称为“流式读取”或“顺序访问”,它适用于处理大型字段(如 varbinary(max)、varchar(max) 等),能有效减少内存占用,避免一次性加载整个结果集。
什么是 CommandBehavior.SequentialAccess?
这是 ADO.NET 提供的一种命令行为选项,启用后:
- 必须按列顺序读取数据,不能跳列访问
- 适合读取大文本或二进制字段(如图片、文件)
- 数据以流的形式逐步读取,而不是全部缓存在内存中
- 显著降低内存峰值,提升处理大数据时的性能
如何在 C# 中启用顺序访问模式
以下是一个使用 SqlCommand.ExecuteReader 并启用 SequentialAccess 的示例:
using (var connection = new SqlConnection(connectionString)) { connection.Open(); using (var command = new SqlCommand("SELECT Id, Content FROM Documents", connection)) { // 启用顺序访问模式 using (var reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) { while (reader.Read()) { int id = reader.GetInt32(0); <pre class='brush:php;toolbar:false;'> // 假设 Content 是 varchar(max) 或 varbinary(max) // 必须从指定偏移开始读取 long bufferSize = 1024; byte[] buffer = new byte[bufferSize]; long bytesRead; long fieldOffset = 0; using (var fileStream = File.Create($"doc_{id}.txt")) { do { bytesRead = reader.GetBytes(1, fieldOffset, buffer, 0, buffer.Length); if (bytesRead > 0) { fileStream.Write(buffer, 0, (int)bytesRead); fieldOffset += bytesRead; } } while (bytesRead == bufferSize); } } } }
}
如果是文本字段(如 nvarchar(max)),可使用 GetChars 和 GetTextReader 来流式读取字符数据。
适用场景与注意事项
- 处理大字段时优先使用 SequentialAccess,避免 OutOfMemoryException
- 必须按列顺序访问,比如先读第0列,再读第1列,不能回头读前面的列
- 一旦跳过某部分数据,无法回退重新读取
- DataReader 在 SequentialAccess 模式下不支持索引器直接获取复杂类型
基本上就这些。虽然没有叫“平面缓冲区模式”的标准功能,但 CommandBehavior.SequentialAccess + DataReader 就是你需要的高效流式读取方案。