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

C# SqlBulkTools的BulkInsertOrUpdate是否支持Where子句?如何过滤更新记录?

解决SqlBulkTools批量合并时按updatedAt过滤更新的问题

SqlBulkTools的BulkInsertOrUpdate确实没有内置Where子句来控制更新条件,不过可以通过以下两种方案实现你的需求:

方案一:本地提前筛选符合条件的记录

先从服务器查询目标表中匹配Id的记录的updatedAt值,在本地筛选出新增记录(Id不存在于服务器)或本地更新时间晚于服务器的记录,再用BulkInsertOrUpdate处理筛选后的集合:

// 从服务器获取现有记录的Id与updatedAt映射
var existingUpdatedAtMap = conn.Query<(Guid Id, DateTime UpdatedAt)>("SELECT id, updatedAt FROM TABLENAME WHERE id IN @Ids", 
    new { Ids = records.Select(r => r.Id) })
    .ToDictionary(item => item.Id, item => item.UpdatedAt);

// 筛选要处理的记录
var filteredRecords = records.Where(r => 
    !existingUpdatedAtMap.ContainsKey(r.Id) || r.UpdatedAt > existingUpdatedAtMap[r.Id]
).ToList();

// 执行批量操作
result += new BulkOperations()
    .Setup<TABLENAME>()
    .ForCollection(filteredRecords)
    .WithTable("TABLENAME")
    .AddAllColumns()
    .CustomColumnMapping(a => a.UpdatedAt, "updatedAt")
    .CustomColumnMapping(a => a.CreatedAt, "createdAt")
    .CustomColumnMapping(a => a.Deleted, "deleted")
    .CustomColumnMapping(a => a.Id, "id")
    .BulkInsertOrUpdate()                                
    .MatchTargetOn(x => x.Id)
    .Commit(conn);

这种方式逻辑直观,适合数据量中等的场景,缺点是需要额外查询服务器数据。

方案二:自定义MERGE语句(底层级控制)

SqlBulkTools的批量更新底层依赖SQL的MERGE语句,你可以手动构建MERGE逻辑,先将数据批量导入临时表,再执行带条件的MERGE:

// 1. 将数据批量导入临时表
var bulkSetup = new BulkOperations()
    .Setup<TABLENAME>()
    .ForCollection(records)
    .WithTable("#TempTABLENAME")
    .AddAllColumns()
    .CustomColumnMapping(a => a.UpdatedAt, "updatedAt")
    .CustomColumnMapping(a => a.CreatedAt, "createdAt")
    .CustomColumnMapping(a => a.Deleted, "deleted")
    .CustomColumnMapping(a => a.Id, "id")
    .BulkInsert()
    .WithTempTable(); // 启用临时表模式

bulkSetup.Commit(conn);

// 2. 执行自定义MERGE,仅当服务器updatedAt小于本地时更新
var mergeCommand = @"
MERGE INTO TABLENAME AS target
USING #TempTABLENAME AS source
ON target.id = source.id
WHEN NOT MATCHED THEN
    INSERT (id, updatedAt, createdAt, deleted)
    VALUES (source.id, source.updatedAt, source.createdAt, source.deleted)
WHEN MATCHED AND target.updatedAt < source.updatedAt THEN
    UPDATE SET
        updatedAt = source.updatedAt,
        createdAt = source.createdAt,
        deleted = source.deleted;
";

conn.Execute(mergeCommand);

// 3. 清理临时表
conn.Execute("DROP TABLE #TempTABLENAME");

这种方式直接在数据库层面处理过滤逻辑,避免本地数据传输开销,适合大数据量场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:18:33