【发布时间】:2016-10-28 18:13:48
【问题描述】:
我对 SQL 还很陌生,并试图找出添加一些预定义数据的最佳方法。我在这里搜索发现我应该使用参数化命令来避免 sql 注入攻击,在这种情况下这不是一个大问题,但我想避免这种可能性并学会正确地做......无论如何这里是我现在的代码:
using (SqlTransaction trans = connection.BeginTransaction())
{
foreach (IEnumerable<string> row in table.RowData)
{
using (SqlCommand sql = new SqlCommand("INSERT INTO " + table.Title
+ " (" + string.Join(", ", table.Headers)
+ ") VALUES (" + string.Join(", ", table.Headers.Select(x => "@" + x)) + ");", connection, trans))
{
for (int i = 0; i < table.Headers.Count(); i++)
{
if (string.IsNullOrEmpty(row.ElementAt(i)))
{ sql.Parameters.AddWithValue("@" + table.Headers.ElementAt(i), DBNull.Value); }
else
{ sql.Parameters.AddWithValue("@" + table.Headers.ElementAt(i), row.ElementAt(i)); }
}
sql.ExecuteNonQuery();
}
}
trans.Commit();
}
这似乎有效,所有数据都进入了那里,但对我来说“感觉”效率低下。我将它包装在一个事务中,所以只有一个提交,但它每次都创建参数,只是为每一行设置不同的值。
有没有办法让它使用相同的参数但只为每行设置不同的值?还是这是最好的方法,我不应该担心?
提前感谢您提供的任何帮助。
【问题讨论】:
-
c# 中的对象很便宜。能不能更有效率?可能。但是你不会通过重用一个参数来获得很多东西,你甚至可能会通过这样做引入一些微妙的错误。我建议不要这样做。
-
有了更多的上下文,我们可以提供更好的帮助,因为我们不知道这是否应该是 SQL API 的可重用包装器、具有大量插入语句和值的特定查询,还是什么- 答案取决于。
-
很抱歉不得不告诉您这一点,但这很容易受到注入攻击——您将变量字符串 (table.Title) 连接到查询中。
-
另外,如果您没有执行回滚的代码,我认为包装事务没有任何意义。如果您这样做,则更有可能出现死锁。
-
不,您不能对表名和列名使用参数,只能使用值。
标签: c# sql .net sql-server database