导读:本期聚焦于小伙伴创作的《C#怎么实现数据导入功能?如何批量导入Excel和CSV到数据库》,敬请观看详情。把Excel或CSV里的几千行记录直接写进数据库,如果一行行Insert,连接开销和事务等待会让导入耗时成倍增长。更麻烦的是用户上传的文件常带空行、类型不一致、编码混乱等问题,程序稍不留神就抛异常。其实在C#里可以借助NuGet上的MiniExcel或CsvHelper先把文件映射成强类型集合,再用SqlBulkCopy做批量写入,比循环插入快十倍以上。本文以SQL Server为例,演示如何读取两种格式文件、做基础校验,并通过表值参数或批量复制把数据稳妥落库,同时给出内存与错误处理的实践建议。

在业务系统中,管理员经常需要把Excel或CSV文件里的数据批量灌进数据库。C#作为主流后端语言,可以组合文件解析库与数据库批量写入机制,高效完成这件事。下面从文件读取、数据校验到入库分别说明。

C#怎么实现数据导入功能?如何批量导入Excel和CSV到数据库

一、读取Excel文件

处理Excel最省心的方式是使用MiniExcel这类轻量库,它基于流式读取,不会像旧版ExcelDataReader那样把整个文件加载进内存。我们先通过NuGet安装MiniExcel,然后用一行代码把sheet映射为实体列表。

假设数据库有一张User表,对应实体如下。注意Excel列名最好和实体属性一致,或者用地图配置别名,避免反射失败。

public class UserImport
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

读取代码非常直观。MiniExcel.Query方法返回IEnumerable,配合ToList即可拿到集合。如果文件很大,也可以不ToList,直接在后续流水线中逐条校验后缓冲入库。

using MiniExcelLibs;
using System.Collections.Generic;
using System.IO;

public List<UserImport> ReadExcel(string filePath)
{
    // 默认读取第一个sheet,列名自动匹配属性
    var rows = MiniExcel.Query<UserImport>(filePath).ToList();
    return rows;
}

这种方式的优点是内存占用低,且支持xlsx和xls。缺点是若用户文件列顺序错乱但列名正确仍可用,若列名不对则需写映射。实际项目里建议先抽样检查表头,再决定是否继续。

二、读取CSV文件

CSV比Excel更简单,但没有统一标准,常见坑是分隔符是逗号还是分号、文本是否用引号包裹、编码是UTF-8还是GB2312。CsvHelper能自动处理多数情况,并支持自定义配置。

下面示例用CsvHelper读取CSV,并指定可能的中文编码。如果文件来自Windows导出,往往需用GB2312,否则中文变乱码。

using CsvHelper;
using CsvHelper.Configuration;
using System.Globalization;
using System.IO;
using System.Text;

public List<UserImport> ReadCsv(string filePath)
{
    var config = new CsvConfiguration(CultureInfo.InvariantCulture)
    {
        Encoding = Encoding.GetEncoding("GB2312"),
        HasHeaderRecord = true
    };
    using var reader = new StreamReader(filePath, config.Encoding);
    using var csv = new CsvReader(reader, config);
    var records = csv.GetRecords<UserImport>().ToList();
    return records;
}

读取后同样得到UserImport列表。CsvHelper允许通过ClassMap定义列名映射,比如文件里叫“姓名”而实体叫Name,可写映射消除差异。此外,它能抛出BadDataException,方便我们捕获格式错误行。

对于超大型CSV,也可以改为foreach逐行读取,配合后面批量写入的缓冲逻辑,避免一次性占用太多内存。

三、数据基础校验

无论来源是Excel还是CSV,落库前都要做校验。常见校验包括:必填字段为空、年龄负数、邮箱格式错误、重复主键。我们可以在内存列表上用LINQ快速过滤。

下面示例剔除空名和年龄异常的数据,并简单用正则校验邮箱。生产环境可引入FluentValidation做更复杂的规则。

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

public List<UserImport> Validate(List<UserImport> list)
{
    var emailRegex = new Regex(@"^[^@s]+@[^@s]+.[^@s]+$");
    var valid = list.Where(u =>
        !string.IsNullOrWhiteSpace(u.Name) &&
        u.Age >= 0 && u.Age < 150 &&
        (string.IsNullOrWhiteSpace(u.Email) || emailRegex.IsMatch(u.Email))
    ).ToList();
    return valid;
}

校验阶段建议把被拒绝的行和原因记到另一个列表,最后返回给前端或写日志,让使用者知道哪些数据没导入。不要静默丢弃,否则排查问题很痛苦。

四、批量写入数据库

拿到干净数据后,最关键的是写入方式。若用循环EF SaveChanges,千行数据可能要几秒到几十秒;而SqlBulkCopy走专属协议,万行也常在毫秒级完成。

SqlBulkCopy要求DataTable或IDataReader。我们可以把List转为DataTable,注意列类型要和表一致。下面代码演示批量写SQL Server。

using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;

public void BulkInsert(List<UserImport> list, string connStr)
{
    var table = new DataTable();
    table.Columns.Add("Id", typeof(int));
    table.Columns.Add("Name", typeof(string));
    table.Columns.Add("Age", typeof(int));
    table.Columns.Add("Email", typeof(string));
    foreach (var u in list)
    {
        table.Rows.Add(u.Id, u.Name, u.Age, u.Email);
    }
    using var conn = new SqlConnection(connStr);
    conn.Open();
    using var bulk = new SqlBulkCopy(conn)
    {
        DestinationTableName = "Users",
        BatchSize = 1000
    };
    bulk.WriteToServer(table);
}

BatchSize设为1000表示每批提交一千行,可平衡内存与事务。若表有自增主键,应在UserImport里把Id留空,并在数据库设自增,避免冲突。另外,可包一层事务,但SqlBulkCopy本身已较稳,大事务反而易锁表。

若使用MySQL,可改用MySqlBulkLoader或逐批INSERT多值;PostgreSQL可用COPY命令。思路一致:减少网络往返和单条编译开销。

五、错误处理与内存建议

导入功能常作为后台任务,应捕获文件损坏、数据库连接断线等异常。建议外层try-catch记录失败文件,并给用户提示。对于十万级以上数据,不要一次性ReadExcel再ToList,而是边读边按批入库。

下表对比两种写入方式,方便选型:

方式千行耗时内存占用适用场景
循环Insert2到5秒极少数据或调试
SqlBulkCopy小于100毫秒常规批量导入

最后提醒,上传文件要限制大小和后缀,防止恶意超大文件拖垮服务。结合上面代码,你就能在C#里搭起一个稳健的Excel与CSV批量导入模块。

C#Excel导入CSV批量导入修改时间:2026-08-01 17:54:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。