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

C#中如何剔除List<T>与DbSet<T>双属性匹配的重复数据?

按Description和Date去重后将CSV数据存入数据库

核心思路

先从数据库提取已存在的(Description, Date)组合,用高效的集合类型快速匹配过滤CSV列表,最后批量插入新数据。

实现步骤及代码示例

假设你已经通过依赖注入获取了DbContext实例(比如在Program.cs中通过builder.Services.AddDbContext<YourDbContext>()配置后,用var dbContext = app.Services.GetRequiredService<YourDbContext>()获取):

  1. 查询数据库中已存在的匹配组合
    只提取需要的两个字段,避免加载整个实体,提升性能:
// 注意:如果Date字段包含时间部分,建议只取Date部分避免精度问题
var existingTransactionPairs = await dbContext.Transactions
    .Select(t => new { t.Description, t.Date.Date })
    .ToListAsync();
  1. 转换为HashSet实现快速查找
    HashSet的Contains操作时间复杂度为O(1),远高于循环比对:
var existingPairSet = new HashSet<(string Description, DateTime Date)>(
    existingTransactionPairs.Select(p => (p.Description, p.Date))
);
  1. 过滤CSV列表中的重复数据
    保留数据库中不存在的记录:
var transactionsToAdd = transactionsCSV
    .Where(t => !existingPairSet.Contains((t.Description, t.Date.Date)))
    .ToList();
  1. 批量插入并保存到数据库
if (transactionsToAdd.Any())
{
    await dbContext.Transactions.AddRangeAsync(transactionsToAdd);
    await dbContext.SaveChangesAsync();
}

注意事项

  • 时间精度问题:如果CSV中的Date带具体时间,而数据库中只存日期,务必统一取Date部分(如t.Date.Date),避免因时分秒差异导致误判。
  • 大小写敏感:如果需要忽略Description的大小写,可在查询和过滤时统一转成小写/大写:
    // 查询时转小写
    var existingTransactionPairs = await dbContext.Transactions
        .Select(t => new { Description = t.Description.ToLower(), t.Date.Date })
        .ToListAsync();
    // HashSet和过滤时同步转小写
    var existingPairSet = new HashSet<(string Description, DateTime Date)>(
        existingTransactionPairs.Select(p => (p.Description, p.Date))
    );
    var transactionsToAdd = transactionsCSV
        .Where(t => !existingPairSet.Contains((t.Description.ToLower(), t.Date.Date)))
        .ToList();
    
  • 性能优化:如果数据量极大,可考虑分批次查询和插入,避免内存占用过高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 12:15:38