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

C#读取文件夹txt/csv/xml文件导入SQL数据库并避免重复导入的方案

最优实现方案

核心逻辑设计思路

  • 双保险去重机制:从文件层面避免重复处理、从数据库层面避免冗余数据
  • 格式适配解析:针对三类文件分别使用对应解析逻辑,统一映射到CustomerModel
  • 启动单次触发:在应用启动入口嵌入执行逻辑,全程仅执行一次

1. 去重机制实现

1.1 新增文件导入记录表

首先在数据库新增FileImportRecords表,对应模型如下:

public class FileImportRecord
{
    public int Id { get; set; }
    // 文件名+最后修改时间的哈希值,唯一标识文件版本
    public string FileUniqueHash { get; set; }
    public DateTime ImportTime { get; set; }
}

每次读取文件前,先计算文件的唯一哈希(可组合文件名、文件大小、最后修改时间计算MD5值),如果哈希值已存在于导入记录表,直接跳过该文件。

1.2 数据库唯一约束

给Customer表添加业务唯一键约束,就算异常触发重复处理也不会生成冗余数据:

ALTER TABLE Customers 
ADD CONSTRAINT UC_Customer_BizKey 
UNIQUE (CustomerNumber, ProductNumber, Name, Quantity);

可根据实际业务规则调整唯一键的字段组合

2. 多格式文件解析与导入逻辑

可引入第三方库简化解析:CSV/TXT用CsvHelper,XML用系统自带的System.Xml.Linq

// 核心导入方法示例
public async Task ImportFilesAsync()
{
    var targetDir = Path.Combine(AppContext.BaseDirectory, "my-folder");
    var allowedExtensions = new[] { ".txt", ".csv", ".xml" };
    var files = Directory.EnumerateFiles(targetDir, "*.*", SearchOption.TopDirectoryOnly)
        .Where(f => allowedExtensions.Contains(Path.GetExtension(f).ToLower()))
        .ToList();

    foreach (var file in files)
    {
        // 计算文件唯一哈希
        var fileInfo = new FileInfo(file);
        var hashSource = $"{fileInfo.Name}_{fileInfo.Length}_{fileInfo.LastWriteTimeUtc.Ticks}";
        var fileHash = Convert.ToHexString(MD5.HashData(Encoding.UTF8.GetBytes(hashSource)));

        // 检查是否已导入
        if (await _dbContext.FileImportRecords.AnyAsync(r => r.FileUniqueHash == fileHash))
            continue;

        // 解析文件
        List<CustomerModel> customers = Path.GetExtension(file).ToLower() switch
        {
            ".txt" or ".csv" => ParseCsvOrTxt(file),
            ".xml" => ParseXml(file),
            _ => new List<CustomerModel>()
        };

        // 批量插入数据库
        if (customers.Any())
        {
            await _dbContext.Customers.AddRangeAsync(customers);
            // 标记文件已导入
            await _dbContext.FileImportRecords.AddAsync(new FileImportRecord
            {
                FileUniqueHash = fileHash,
                ImportTime = DateTime.UtcNow
            });
            await _dbContext.SaveChangesAsync();
        }
    }
}

// CSV/TXT解析示例(基于CsvHelper)
private List<CustomerModel> ParseCsvOrTxt(string filePath)
{
    using var reader = new StreamReader(filePath);
    using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
    return csv.GetRecords<CustomerModel>().ToList();
}

// XML解析示例
private List<CustomerModel> ParseXml(string filePath)
{
    var doc = XDocument.Load(filePath);
    return doc.Descendants("Customer")
        .Select(x => new CustomerModel
        {
            CustomerNumber = (int)x.Element("CustomerNumber"),
            ProductNumber = (string)x.Element("ProductNumber"),
            Quantity = (int)x.Element("Quantity"),
            Name = (string)x.Element("Name")
        }).ToList();
}

3. 启动时单次执行配置

  • 若为ASP.NET Core项目:在Program.cs中构建完WebApp后,运行启动逻辑再启动服务:
var app = builder.Build();
// 执行导入
using (var scope = app.Services.CreateScope())
{
    var importService = scope.ServiceProvider.GetRequiredService<IImportService>();
    await importService.ImportFilesAsync();
}
app.Run();
  • 若为控制台项目:直接在Main方法入口处调用导入方法即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:15:06