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

EF Core实现同ID多条码商品的高效批量插入方案

问题场景

我们定义了如下两个实体类:

public class Article{
    public int Id {get; set;}
    public double price {get; set;}
    public ICollection<Barcode> barcodes {get; set;}
}

public class Barcode {
   public int Id {get; set;}
   public long Value{get; set;}
   public int ArticleId {get; set;}
   public Article Article {get; set;}
}

解析.csv文件时,会出现同一商品ID对应多行不同数据的情况,示例如下:

  • 行1: 1234 | 591111111111111 | 13.49
  • 行2: 1234 | 591111111111112 | 13.49
    即两个不同的EAN条码可对应同一个Article商品实体。
    待导入的CSV文件包含超过10万行数据,解析CSV后已有如下代码:
List<Article> importedArticles = _csvParseFile(filePath);
// 应如何遍历该集合,最终实现单次调用AddRange完成数据库批量插入?

核心要求:

  • 完全规避O(n*m)时间复杂度的嵌套遍历逻辑
  • 首次遍历到某商品ID时创建对应商品记录,同时添加关联条码
  • 后续遍历到相同商品ID但不同EAN条码时,仅追加关联条码
  • 最终可通过批量插入完成数据落库

实现方案

核心思路是用字典做商品ID到实体实例的O(1)映射,单次线性遍历即可完成去重和关联数据聚合,全程无嵌套循环,时间复杂度严格为O(n)。
注意:默认_csvParseFile返回的集合是逐行解析的原始结果——即每一行CSV对应一个Article实例,同ID的商品会重复出现在列表中,每个实例仅携带当前行对应的单个条码。如果解析方法已经做了不完整的分组,先调整解析逻辑输出逐行的扁平结构即可。

具体实现代码

// 存储商品ID与对应去重后的Article实体,查找/插入时间复杂度O(1)
var articleDict = new Dictionary<int, Article>();
// 存储所有需要插入的条码记录
var allBarcodes = new List<Barcode>();

// 单次遍历所有解析结果
foreach (var rowItem in importedArticles)
{
    // 尝试从字典中获取已创建的商品实例
    if (!articleDict.TryGetValue(rowItem.Id, out var existingArticle))
    {
        // 首次遇到该商品ID,新建实体
        existingArticle = new Article
        {
            Id = rowItem.Id,
            price = rowItem.price,
            barcodes = new List<Barcode>()
        };
        articleDict.Add(rowItem.Id, existingArticle);
    }

    // 提取当前行对应的条码,取值逻辑按你实际的_csvParseFile输出结构调整
    var currentBarcode = rowItem.barcodes.First();
    currentBarcode.ArticleId = existingArticle.Id;
    currentBarcode.Article = existingArticle;
    
    // 关联条码到商品,加入总条码列表
    existingArticle.barcodes.Add(currentBarcode);
    allBarcodes.Add(currentBarcode);
}

// 提取所有去重后的商品
var articlesToInsert = articleDict.Values.ToList();

// 批量插入,两次AddRange即可完成
_dbContext.Articles.AddRange(articlesToInsert);
_dbContext.Barcodes.AddRange(allBarcodes);
_dbContext.SaveChanges();

方案说明

  • 整个流程仅做一次线性遍历,字典操作均为O(1),10万行数据处理耗时通常在百毫秒以内
  • 无需提前对数据做排序、全量分组操作,内存占用仅和去重后的商品数、总条码数正相关
  • 如果业务要求条码值全局唯一,可额外增加一个HashSet<long>存储已处理的条码值,遍历过程中做重复校验,避免脏数据入库
  • 如果使用支持批量插入的ORM(比如SqlBulkCopy、EFCore.BulkExtensions),可以直接将两个列表传入做高性能bulk insert,10万行数据导入耗时可控制在1秒内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:15:31