Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SqlCommand Parameters vs. String.Format [duplicate]

I've been searching on the internet, but I just can't seem to find anything that explain my question (could be that I'm not using the correct search string), so I'm posting here hoping that someone can help me with this. (My program is written is C# using Visual Studio 2010)

I notice that in C#, there are multiple ways of constructing a SQL command.

SqlConnection connection = GetAndOpenConnection(); //function containing connection string and open connection
SqlCommand command = connection.CreateCommand();

Up to this point, I have no questions. The problem I have is with CommandText. I am using several different commands in my code(SELECT/INSERT/UPDATE/DELETE), but lets take SELECT for example.

//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"));

What are the differences between the above 2 examples? (performance wise/structure wise/etc)

The reason I'm asking is because within the same .cs file, when I use the method in Example 2, sometime the code works properly and sometime it doesn't, then I eventually makes everything like in Example 1, which works every single time.

Is there a significant gain/loss using either method? Which is the more proper way of completing a task like this?

ADDITIONAL QUESTION

Okay, so I see that method 2 is the more appropriate way to do this.

However, there's a problem if I use method 2.

I have a loop that loop through a List<string> names. Inside the loop, when I use method 2 and add name as parameters, I got an error saying that the parameter already exist and cannot be added.

How can I go about solving this?

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
    }
}

Also, I know that people mentioned that in the parameter it should be "@myName" instead of "myName". I remember having this issue as I was confused which way to use and had to just test it. "@myName" was not working for me but "myName" is, and this is how it's in the code right now in the parts where I still use method 2. I'm using .Net 4.0, don't know if this will make a difference.

like image 437
sora0419 Avatar asked Mar 03 '14 17:03

sora0419


People also ask

Does string format prevent SQL injection?

Simply using String. Format does not protect against SQL injection attacks.

Does string interpolation prevent SQL injection?

Accepts a query string with placeholders for values, and returns a string with the values embedded. The function is careful to quote all of its inputs with dbQuoteLiteral() to protect against SQL injection attacks.

What is Sqlcommand parameters AddWithValue?

AddWithValue replaces the SqlParameterCollection. Add method that takes a String and an Object. The overload of Add that takes a string and an object was deprecated because of possible ambiguity with the SqlParameterCollection.


1 Answers

Parameters exist to prevent SQL Injection. For example, consider what happens in case of string.Format if instead of bob there was TextBox1.Text which contained 1';DROP TABLE myTable;'.

SQL Injection is not possible if you have complete control over the parameters, like in your case with string literal for parameter. However you never know how your code might change in future, so as a rule of thumb you should always stick to safer approach with parameters.

If you are facing some particular problems with second approach - search and maybe post here, there is most likely a solution already. For example, in your code snippet actual parameter name is @myName with @ symbol, and that is what should be supplied to the SqlParameter constructor.

Update. In your additional question problem is exactly in parameters naming - it should be @myName:

command.Parameters.Add(new SqlParameter("@myName", name));

Also you should clear parameters collection on each iteration:

command.Parameters.Clear();

Although it would be better to create new command on every iteration to avoid mess - check this thread for details.

like image 97
Andrei Avatar answered Oct 03 '22 14:10

Andrei