Mam tabelę Project
z dwiema kolumnami - ProjectId
i ProjectName
- i piszę funkcję, która tworzy i wykonuje SqlCommand
, aby wysłać zapytanie do bazy danych o identyfikatorach projektu o podanej nazwie. Polecenie to działa, ale jest podatny na SQL Injection:Dlaczego String.Format działa, ale SqlCommand.Parameters.Add nie?
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
i idValue
są wszystkie ciągi. Na przykład mogą być odpowiednio: "ProjectId"
, "Project"
, "ProjectName"
i "MyFirstProject"
. surroundWithSingleQuotes
otacza ciąg znaków z ''
, czyli surroundWithSingleQuotes(idValue) == "'MyFirstProject'"
. Próbuję napisać tę funkcję tak ogólną, jak to tylko możliwe, ponieważ mógłbym chcieć uzyskać cały dany atrybut z tabeli w przyszłości.
Chociaż powyższy String.Format działa, to nie:
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);
...
}
nie jestem pewien dlaczego. Nie otrzymuję komunikatu o błędzie, ale kiedy napiszę DataTable
używając SqlDataAdapter
, DataTable nie zawiera nic. Oto różne podejścia wziąłem, bezskutecznie:
- Po this answer i Microsoft's documentation, wykorzystujące
AddWithValue
lub wykorzystująceParameters.Add
iSqlParameter.Value
. - Selektywne zastępowanie
{0}
,{1}
,{2}
i{3}
wString.Format
z rzeczywistą wartością lub ciągiem parametrów.
W innych miejscach w moim kodzie użyłem sparametryzowanych zapytań (choć z jednym parametrem) bez problemu.
Jedynymi parametrami elementów, które można bezpośrednio zastąpić, jest '{3}'. –
Nie można użyć parametru dla nazwy kolumny. Wciąż będziesz musiał użyć do tego 'string.Format', podobnie jak w przypadku nazwy tabeli. – juharr