使用SqlCommand作为multidelete语句

时间:2016-08-27 10:47:39

标签: c# sql sql-injection

我想根据其ID从数据库中删除行。我们来看看我当前的代码

private static SqlCommand GenerateDeleteCommand(SqlConnection connection, string table, IEnumerable<int> ids)
{
    var idList = ids.ToList();
    var command = new SqlCommand($"delete from {table} where Id in ({string.Join(", ", idList)}", connection);
    return command;
}

它可能不需要任何解释。但是,我尝试使用占位符(主要是首选方式)

private static SqlCommand GenerateDeleteCommand2(SqlConnection connection, string table, IEnumerable<int> ids)
{
    var idList = ids.ToList();
    var command = new SqlCommand($"delete from {table} where Id in ({string.Join(", ", idList.Select(x => $"@{x}"))})", connection);

    idList.ForEach(x => command.Parameters.Add($"@{x}", SqlDbType.Int));
    idList.ForEach(x => command.Parameters[$"@{x}"].Value = x);

    return command;
}

但这对我来说似乎很愚蠢。在这种情况下,对于数据类型,没有什么可以出错。我在这里传递强类型集合,因此值必须是整数,并且没有SQL注入的风险。当然,传递表名可能存在风险,但我们假设我们总是传递一个包含表名的预定义const字符串。

我的问题是,我们在第二种情况下是否有任何优势(这会让我们失去一些性能)。

1 个答案:

答案 0 :(得分:1)

Sql Server和大多数其他数据库提供程序必须为每个传入查询生成查询计划。可以重用这些查询计划,查询计划与传入的查询文本匹配。因此,如果执行使用参数的查询,即使使用不同的参数,查询文本本身也保持不变。这允许Sql Server缓存计划以及创建和维护查询执行的统计信息。如果将参数值注入查询字符串,则每次执行查询时都必须创建一个新计划,效率要低得多。

有关此问题的详细信息,请参阅Execution Plan Caching and Reuse