You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 8 MVC:如何从SQL查询导出带类型数据至Excel

解决ASP.NET Core MVC中带类型导出Excel的问题

方案一:基于IDataReader处理类型并赋值

直接转字符串会丢失所有类型信息,而直接赋值dr.GetValue(j)的问题主要是未处理DBNull.Value,同时需要根据字段类型明确转换值,确保Excel识别原生类型。以下是修正后的代码:

public async Task<IActionResult> RawData() 
{
    using var workbook = new XLWorkbook();
    var worksheet = workbook.Worksheets.Add("Test");
    using IDataReader dr = ExecuteReader("select * from foo", out IDbConnection _);

    // 写入表头(提升Excel可读性)
    for (int j = 0; j < dr.FieldCount; j++)
    {
        worksheet.Cell(1, j + 1).Value = dr.GetName(j);
        worksheet.Cell(1, j + 1).Style.Font.Bold = true;
    }

    int currentRow = 2;
    while (dr.Read())
    {
        for (var j = 0; j < dr.FieldCount; j++)
        {
            if (dr.GetFieldType(j) == typeof(byte[]))
                continue; // 跳过二进制数据

            object value = dr.IsDBNull(j) ? null : dr.GetValue(j);
            var cell = worksheet.Cell(currentRow, j + 1);

            // 根据字段类型赋值,确保Excel识别正确类型
            switch (Type.GetTypeCode(dr.GetFieldType(j)))
            {
                case TypeCode.Boolean:
                    cell.Value = (bool?)value;
                    break;
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                    cell.Value = Convert.ToInt64(value);
                    break;
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    cell.Value = Convert.ToDecimal(value);
                    break;
                case TypeCode.DateTime:
                    cell.Value = (DateTime?)value;
                    break;
                default: // 字符串、GUID等其他类型
                    cell.Value = value?.ToString();
                    break;
            }
        }
        currentRow++;
    }

    using var stream = new MemoryStream();
    workbook.SaveAs(stream);
    stream.Position = 0; // 重置流位置,避免文件损坏

    return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "test.xlsx");
}

关键优化点

  • 新增表头写入,提升导出文件的可读性
  • 用dr.IsDBNull(j)判断空值,避免DBNull.Value直接赋值导致的异常
  • 通过TypeCode区分数据类型,将值转换为对应类型后赋值,保证Excel识别数字、日期、布尔等原生类型
  • 重置MemoryStream位置,防止导出文件损坏

方案二:使用EF Core FromSQLRawAsync结合动态类型

如果应用已使用Entity Framework Core,可以利用FromSQLRawAsync查询动态数据,自动保留原始类型,无需手动判断字段类型:

using Microsoft.EntityFrameworkCore;

public async Task<IActionResult> RawDataWithEF()
{
    using var workbook = new XLWorkbook();
    var worksheet = workbook.Worksheets.Add("Test");

    // 执行原生SQL查询,返回动态对象列表
    var data = await _dbContext.Database.FromSqlRaw("select * from foo")
        .AsEnumerable()
        .ToListAsync();

    if (!data.Any())
        return File(new byte[0], "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "empty.xlsx");

    // 获取属性名并写入表头
    var properties = data.First().GetType().GetProperties();
    for (int i = 0; i < properties.Length; i++)
    {
        worksheet.Cell(1, i + 1).Value = properties[i].Name;
        worksheet.Cell(1, i + 1).Style.Font.Bold = true;
    }

    // 写入数据行
    int currentRow = 2;
    foreach (var item in data)
    {
        for (int i = 0; i < properties.Length; i++)
        {
            var value = properties[i].GetValue(item);
            var cell = worksheet.Cell(currentRow, i + 1);
            
            // 处理DBNull,直接赋值保留原始类型
            cell.Value = value == DBNull.Value ? null : value;
        }
        currentRow++;
    }

    using var stream = new MemoryStream();
    workbook.SaveAs(stream);
    stream.Position = 0;

    return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "test_ef.xlsx");
}

关键说明

  • 需要注入你的DbContext实例(_dbContext)
  • FromSQLRawAsync返回的动态对象会自动保留数据库原始类型,无需手动判断转换
  • 同样处理DBNull转null的逻辑,避免Excel识别异常

内容的提问来源于stack exchange,提问作者Andrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:45:14