【问题标题】:How to pass multiple records to update with one sql statement in Dapper如何在 Dapper 中使用一条 sql 语句传递多条记录以进行更新
【发布时间】:2015-09-17 16:23:28
【问题描述】:

我正在尝试使用单个 Update 语句来更新具有不同值的多条记录(我不是在尝试更新许多行以具有相同的值,这非常简单)。这是我现在正在尝试的:

    using (var cn = GetOpenConnection()) {

        // get items where we need to set calculated fields that will now be persisted in the DB
        var items = cn.Query<MaintenanceItem>("select TOP 500 * from [Maintenance] where Tolerance IS NOT NULL");

        foreach (var mi in maintItems)
        {
            // Set calculated fields on multiple recrods
            logic.CalculateToleranceFields(mi, true);
        }


        var updateInput = items.Select(a => new {a.ToleranceMonths, a.ToleranceDays, a.ToleranceHours, a.ToleranceLandings, a.ToleranceCycles, a.ToleranceRIN }).ToList();

       // THIS DOESN'T WORK - attempting to update multiple rows with different values
       var numResults = cn.Execute(@"UPDATE rm 
                SET rm.ToleranceMonths=ur.ToleranceMonths, 
                rm.ToleranceDays=ur.ToleranceDays, 
                rm.ToleranceHours=ur.ToleranceHours, 
                rm.ToleranceLandings=ur.ToleranceLandings, 
                rm.ToleranceCycles=ur.ToleranceCycles, 
                rm.ToleranceRIN=ur.ToleranceRIN 
            from [RoutineItems] rm
            Inner Join @UpdatedRecords ur ON rm.AircraftId=ur.AircraftId AND rm.ItemNumber=ur.ItemNumber", updateInput);

        Assert.IsTrue(numResults == maintItems.Count());

    }

Dapper 可以进行这种批量更新吗?我宁愿批量更新,也不愿使用 for 循环将数据推送到数据库中。

【问题讨论】:

  • 你可以在 Sql Server 中创建一个用户类型,或者你可以通过使用 XML 和创建临时表等来模拟批量插入功能。做一个谷歌搜索,网上有很多例子。

标签: c# sql-server dapper


【解决方案1】:

目前看来,Dapper 中的一条语句无法实现这一点。当考虑在幕后需要做些什么来实现这一点时,这是完全可以理解的。

我最终做的是使用 3 条语句来创建一个临时表,将需要更新的数据填充到其中,然后使用我的临时表的内部连接调用更新:

cn.Execute(@"create table #routineUpdatedRecords
                        (
                            AircraftId int, 
                            ItemNumber int,
                            ToleranceMonths int,
                            ToleranceDays int,
                            ToleranceLandings int,
                            ToleranceCycles decimal(12,2),
                            ToleranceRIN decimal(12,2),
                            ToleranceHours decimal(12,2)
                        );");


cn.Execute(@"Insert INTO #routineUpdatedRecords 
    VALUES(@AircraftId, @ItemNumber, @ToleranceMonths, @ToleranceDays, 
@ToleranceLandings, @ToleranceCycles, @ToleranceRIN, @ToleranceHours)", updateInput);

var numResults = cn.Execute(@"UPDATE rm 
                                SET rm.ToleranceMonths=ur.ToleranceMonths, 
                                rm.ToleranceDays=ur.ToleranceDays, 
                                rm.ToleranceHours=ur.ToleranceHours, 
                                rm.ToleranceLandings=ur.ToleranceLandings, 
                                rm.ToleranceCycles=ur.ToleranceCycles, 
                                rm.ToleranceRIN=ur.ToleranceRIN 
                            from [RoutineItems] rm
                            Inner Join #routineUpdatedRecords ur ON rm.AircraftId=ur.AircraftId AND rm.ItemNumber=ur.ItemNumber");

我相信这比在循环中调用 update 更快,因为我更新了大约 600K 行。

【讨论】:

  • 嗨,Kento,我们到底需要删除#routineUpdatedRecords 吗?
  • @ThienLong 我认为没有必要删除临时表,因为它是在创建它的会话/连接中计分的。当您的 dapper 查询完成后,此会话将关闭,因为 sql server 删除了临时表。 social.msdn.microsoft.com/Forums/sqlserver/en-US/…
【解决方案2】:

我知道线程有点旧。但是,您可以这样做,而不是使用临时表。提供更好的语法。

string sql = @"UPDATE rm 
    SET rm.ToleranceMonths=@ToleranceMonths, 
    rm.ToleranceDays=@ToleranceDays, 
    rm.ToleranceHours=@ToleranceHours, 
    rm.ToleranceLandings=@ToleranceLandings, 
    rm.ToleranceCycles=@ToleranceCycles, 
    rm.ToleranceRIN=@ToleranceRIN 
    FROM [RoutineItems] rm
    WHERE rm.AircraftId=@AircraftId AND rm.ItemNumber=@ItemNumber
    ";

var numResults = cn.Execute(sql, updateInput);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    相关资源
    最近更新 更多