首页 > 解决方案 > SQL MERGE语句用Dapper一一运行记录

问题描述

所以我正在使用这样的MERGE语句查询Dapper

string sql = @$"MERGE Internal.AssessmentStrategy AS TARGET
                USING (VALUES (@Id, @AssessmentId, @StrategyId, @CreatedBy, @CreatedAt, @UpdatedAt)) AS SOURCE (Id, AssessmentId, StrategyId, CreatedBy, CreatedAt, UpdatedAt)
                ON SOURCE.AssessmentId = TARGET.AssessmentId AND SOURCE.StrategyId = TARGET.StrategyId
                WHEN NOT MATCHED BY TARGET
                THEN INSERT (Id, AssessmentId, StrategyId, CreatedAt, CreatedBy, UpdatedAt) 
                VALUES (SOURCE.Id, SOURCE.AssessmentId, SOURCE.StrategyId, SOURCE.CreatedAt, SOURCE.CreatedBy, SOURCE.UpdatedAt)
                WHEN NOT MATCHED BY SOURCE
                THEN DELETE;
                  ";
    
    var source = request.StrategyIds.ToList<Guid>().Select(s => new
    {
        Id = Guid.NewGuid(),
        AssessmentId = request.AssessmentId,
        StrategyId = s,
        CreatedBy = request.UserId,
        CreatedAt = DateTime.Now,
        UpdatedAt = DateTime.Now
    });
    
    await connection.ExecuteAsync(sql, source);

基本上发生的事情是,Dapper 正在为我传递的每条记录运行此语句,SOURCE而不是一次性针对所有记录,因此无论我传递什么记录SOURCE,查询完成后只有最后一个保留在目标中其余的都被删除。

所以基本上,这就是正在发生的事情,比如说

目标有1

来源有1, 2, 3

那么dapper正在做的是

  1. 它运行对 SOURCE 的第一条记录的查询,1发现它已经存在于 TARGET 中,所以什么也不做

  2. 然后它运行它进行记录2,发现1必须从 TARGET 中删除并且2必须插入,所以现在 TARGET 留下了记录2

  3. 然后它运行它进行记录3,发现2必须从 TARGET 中删除并且3必须插入,所以最后 TARGET 留下了值3

所以每次 TARGET 都会留下我通过的最后一条记录。

我不知道如何让它像一张记录表而不是单个记录一样一次性考虑所有记录。

任何想法?

标签: sqlsql-servertsqlmergedapper

解决方案


推荐阅读