I have a Project
table with two columns -- ProjectId
and ProjectName
-- and am writing a function that constructs and executes a SqlCommand
to query the database for the ids of a Project with a given name. This command works, but is vulnerable to SQL Injection:
string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}",
attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue));
SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable attributes = new DataTable();
adapter.Fill(attributes);
...
}
attributeParam
, tableParam
, idParam
, and idValue
are all strings. For example, they might be "ProjectId"
, "Project"
, "ProjectName"
, and "MyFirstProject"
, respectively. surroundWithSingleQuotes
surrounds a string with ''
, so surroundWithSingleQuotes(idValue) == "'MyFirstProject'"
. I am trying to write this function as general as possible since I might want to get all of a given attribute from a table in the future.
Although the above String.Format works, this doesn't:
string sqlCommand = String.Format("SELECT @attributeparam FROM {0} WHERE " +
"@idparam = @idvalue", tableParam);
command.Parameters.Add(new SqlParameter("@attributeparam", attributeParam));
command.Parameters.Add(new SqlParameter("@idparam", idParam));
command.Parameters.Add(new SqlParameter("@idvalue",
surroundWithSingleQuotes(idValue)));
SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable attributes = new DataTable();
adapter.Fill(attributes);
...
}
I'm not sure why. I get no error message, but when I fill my DataTable
using a SqlDataAdapter
, the DataTable contains nothing. Here are various approaches I've taken, to no avail:
- Following this answer and Microsoft's documentation, using
AddWithValue
or usingParameters.Add
andSqlParameter.Value
. - Selectively replacing
{0}
,{1}
,{2}
, and{3}
inString.Format
with either the actual value or the parameter string.
In other places in my code, I've used parametrized queries (although with just one parameter) no problem.