SqlCommand参数与String.Format

sor*_*419 4 c# sql parameters command

我一直在互联网上搜索,但我似乎无法找到解释我的问题的任何东西(可能是我没有使用正确的搜索字符串),所以我发帖在这里希望有人可以帮助我有了这个.(我的程序是使用Visual Studio 2010编写的C#)

我注意到在C#中,有多种构造SQL命令的方法.

SqlConnection connection = GetAndOpenConnection(); //function containing connection string and open connection
SqlCommand command = connection.CreateCommand();
Run Code Online (Sandbox Code Playgroud)

到目前为止,我没有任何问题.我遇到的问题是CommandText.我在我的代码中使用了几个不同的命令(SELECT/ INSERT/ UPDATE/ DELETE),但SELECT举个例子.

//Example 1:
command.CommandText = String.Format("SELECT * FROM myTable WHERE name = '{0}'", "bob");

//Example 2:
command.CommandText = "SELECT * FROM myTable WHERE name = @myName";
command.Parameters.Add(new SqlParameter("myName", "bob"));
Run Code Online (Sandbox Code Playgroud)

上面两个例子之间有什么区别?(表现明智/结构明智/等)

我问的原因是因为在同一个.cs文件中,当我使用示例2中的方法时,有时候代码正常工作而有时它没有,那么我最终会像示例1中那样生成所有内容,每个单独工作时间.

使用任何一种方法都有显着的收益/损失吗?完成这样的任务的更合适的方法是什么?

其他问题

好的,所以我看到方法2是更合适的方法.

但是,如果我使用方法2则会出现问题.

我有一个循环循环通过List<string> names.在循环内部,当我使用方法2并添加名称作为参数时,我得到一个错误,说该参数已经存在且无法添加.

我怎样才能解决这个问题?

List<string> names = new List<string> {"adam", "bob", "john"};
foreach(string name in names)
{
    command.CommandText = "SELECT * FROM myTable WHERE name = @myName";
    command.Parameters.Add(new SqlParameter("myName", name));
    reader = command.ExecuteReader();

    while(reader.Read())
    {
        //loop through each cell and print on the Console
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,我知道人们提到在参数中它应该"@myName"代替"myName".我记得有这个问题,因为我很困惑哪种方式使用,只能测试它."@myName"不是我的工作,但是"myName",这就是我现在在代码中仍然使用方法2的代码.我正在使用.Net 4.0,不知道这是否有所作为.

And*_*rei 8

存在用于防止SQL注入的参数.例如,考虑在以下情况下会发生什么string.Format,如果不是bobTextBox1.Text含有1';DROP TABLE myTable;'.

如果您完全控制参数,则无法进行SQL注入,例如参数的字符串文字.但是,您永远不知道您的代码将来会如何变化,因此根据经验,您应该始终坚持使用参数更安全的方法.

如果您在使用第二种方法时遇到一些特殊问题 - 搜索并在此处发布,则很可能已经有了解决方案.例如,在您的代码片段中,实际参数名称@myName带有@符号,这是应该提供给SqlParameter构造函数的内容.

更新.在您的其他问题中,问题恰好在参数命名中 - 它应该是@myName:

command.Parameters.Add(new SqlParameter("@myName", name));
Run Code Online (Sandbox Code Playgroud)

您还应该清除每次迭代的参数集合:

command.Parameters.Clear();
Run Code Online (Sandbox Code Playgroud)

虽然最好在每次迭代时创建新命令以避免混乱 - 请查看此线程以获取详细信息.


Nic*_*rey 5

如前所述,第一个(动态)查询容易受到SQL注入攻击。而且,每次执行时都必须重新编译它,从而增加了执行成本(并可能在编译时阻塞)。

第二个(参数化的)查询不容易受到SQL注入攻击。此外,它的执行计划可以被缓存,这样它在第一次执行时只被编译一次。至少直到高速缓存过期或由于某种原因而被刷新为止。