我想根据其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字符串。
我的问题是,我们在第二种情况下是否有任何优势(这会让我们失去一些性能)。
答案 0 :(得分:1)
Sql Server和大多数其他数据库提供程序必须为每个传入查询生成查询计划。可以重用这些查询计划,查询计划与传入的查询文本匹配。因此,如果执行使用参数的查询,即使使用不同的参数,查询文本本身也保持不变。这允许Sql Server缓存计划以及创建和维护查询执行的统计信息。如果将参数值注入查询字符串,则每次执行查询时都必须创建一个新计划,效率要低得多。
有关此问题的详细信息,请参阅Execution Plan Caching and Reuse