关于c#:WHERE IN与ExecuteSqlCommand一起使用的原始SQL查询不适用于多个记录

WHERE IN Raw SQL Query used with ExecuteSqlCommand not working for multiple records

我正在尝试在更新多个记录时有效地使用UPDATE查询(而不是为每个Id循环)。

我有这个简单的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    public static async Task EfficientlyUpdateSentTimeforSomeTicketsAsync(List<int> Ids)
    {
        var parameters = Ids.Select((id, index) => new SqlParameter(string.Format("@p{0}", index), id));
        var parameterNames = string.Join(",", parameters.Select(p => p.ParameterName));
        var query = string.Format("Update [TicketQueueTable] Set SentDatetime = {1} WHERE TicketQueueID IN ({0})", parameterNames, DateTime.Now);

        try
        {
            using (var db = GetDbContext())
            {
                var affectedRows = await db.Database.ExecuteSqlCommandAsync(query, parameters.ToArray());
            }
        }
        catch (Exception ex)
        {
            await LogErrorAsync(ex);
            throw ex;
        }
    }

我从以下问题中寻求帮助:https://stackoverflow.com/a/43969812/8644294,但我无法完成这项工作。它让我大吃一惊,上面写着:

Incorrect syntax near '2'

为简单起见,我现在要发送的ID是new List<int>() { 1, 2 }

谢谢您的时间。


您正在创建的字符串如下所示:

1
Update [TicketQueueTable] Set SentDatetime = 3/6/2020 2:30:18 AM WHERE TicketQueueID IN (@p0, @p1)

如果尝试使用SQL工具(如SQL Server Management Studio)执行该命令,则会收到此错误。

1
2
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '2'.

加上2:30:18 AM处的2用红色下划线标出。

您有两种选择:

  • 引用日期时间
  • 1
    var query = string.Format("Update [TicketQueueTable] Set SentDatetime = '{1}' WHERE TicketQueueID IN ({0})", parameterNames, DateTime.Now);
  • 使用sql函数获取sql服务器的当前时间
  • 1
    var query = string.Format("Update [TicketQueueTable] Set SentDatetime = GETDATE() WHERE TicketQueueID IN ({0})", parameterNames, DateTime.Now); // GETDATE() for MSSQL NOW() for MySQL
  • 将日期时间作为参数传递
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public static async Task EfficientlyUpdateSentTimeforSomeTicketsAsync(List<int> Ids)
    {
        var parameters = Ids.Select((id, index) => new SqlParameter(string.Format("@p{0}", index), id)).ToList();
        var parameterNames = string.Join(",", parameters.Select(p => p.ParameterName));
        var query = string.Format("Update [TicketQueueTable] Set SentDatetime = @p{1} WHERE TicketQueueID IN ({0})", parameterNames, parameters.Count());

        parameters.Add(new SqlParameter($"@p{parameters.Count()}", DateTime.Now));
        try
        {
            using (var db = GetDbContext())
            {
                var affectedRows = await db.Database.ExecuteSqlCommandAsync(query, parameters.ToArray());
            }
        }
        catch (Exception ex)
        {
            await LogErrorAsync(ex);
            throw ex;
        }
    }


    类似这样的东西:(我没有测试,可能有错字)

    1
    2
    3
    4
    5
    6
    7
    8
    var parameterNames = string.Join(",", Ids.Select(p =>"("+ x.id.ToString()+")"));
    var query = string.Format(@"Update TicketQueueTable
                                  Set SentDatetime = '{1}'
                                 FROM TicketQueueTable
                                 JOIN (
                                   VALUES
                                    {0}
                                 ) AS L(ID) ON TicketQueueTable.Ticket.TicketQueueID = L.ID;"
    , parameterNames, DateTime.Now)

    如果要使用参数(应使用),则将其设置为表参数,并在表中包含值列表并加入该表。