C#导出百万级数据解决方案
·
概要
解决百万级数据导出导致内存溢出问题,之前的方式是把所有数据查询出来,然后循环所有数据插入到文件中上传到云上,这样数据少还行,数据多了内存就溢出了。
解决方案
直接重构代码:使用ADO的SqlDataReader获取数据,这样避免把所有数据加载到内存中(具体工作原理有兴趣的可以去百度下),导出excel使用NPOI的SXSSFWorkbook,用于处理大型 Excel 文件的一个类,它是 XSSFWorkbook 的流式版本,专门用于高效处理大数据量的 Excel 文件,避免内存溢出,下面直接上代码。
class Program1
{
static void Main()
{
string connectionString = "your_connection_string";
string query = "SELECT Name, Age FROM Users";
string SheetName = "sheet1";
List<string> column = new List<string>();
column.Add("Name");
column.Add("Age");
SXSSFWorkbook book = new SXSSFWorkbook();
var sheet = book.CreateSheet(SheetName);
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// 使用 SqlCommand 和 SqlDataReader 以流式方式读取数据
using (var command = new SqlCommand(query, connection))
{
using (var reader = command.ExecuteReader())
{
int rowCount = 1;
while (reader.Read())
{
var row = sheet.CreateRow(rowCount);
//计数
int count = 0;
foreach (var co in column)
{
var cell = row.CreateCell(count);
int columnIndex = reader.GetOrdinal(co);//获取对应字段的索引
string columnType = reader.GetFieldType(columnIndex).Name;//根据索引获取字段类型
var val = reader[columnIndex];//根据索引获取对应的值
if (val == null || val == DBNull.Value || string.IsNullOrWhiteSpace(val?.ToString()))
{
cell.SetCellValue("");
count++;
continue;
}
if (!string.IsNullOrWhiteSpace(columnType))
{
if (columnType.Equals("date", StringComparison.OrdinalIgnoreCase) || columnType.Equals("dateTime", StringComparison.OrdinalIgnoreCase))
{
try
{
//时间转换
DateTime dt;
var flag = DateTime.TryParse(val.ToString(), out dt);
if (flag)
{
val = dt;
}
cell.SetCellValue(val.ToString());
}
catch
{
cell.SetCellValue(Convert.ToString(val));
}
}
else if (columnType.Equals("decimal", StringComparison.OrdinalIgnoreCase))
{
try
{
cell.SetCellValue(Convert.ToDouble(Math.Round(Convert.ToDouble(val), 2)));
}
catch
{
cell.SetCellValue(Convert.ToString(val));
}
}
else
{
cell.SetCellValue(Convert.ToString(val));
}
}
else
{
cell.SetCellValue(Convert.ToString(val));
}
count++;
}
rowCount++;
}
}
}
}
// 1. 创建临时文件路径
string filePath = Path.GetTempFileName();
// 直接写入文件流,避免内存溢出
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
book.Write(fs); // 直接写入文件
book.Close();
book.Dispose();
}
//上传文件
var storage = GetStorageService();
using (FileStream fileStream = File.OpenRead(filePath))
{
var uploadResult = storage.UploadFile(fileStream, fileName);
}
File.Delete(filePath);
}
}
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)