Możesz sparametryzować każdy wartość, więc coś takiego:
string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";
string[] paramNames = tags.Select(
(s, i) => "@tag" + i.ToString()
).ToArray();
string inClause = string.Join(", ", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
for(int i = 0; i < paramNames.Length; i++) {
cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
}
}
Co da ci:
cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0, @tag1, @tag2, @tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"
Nie, nie jest to otwarte na wstrzyknięcie SQL. Jedyny tekst wstrzykiwany do CommandText nie jest oparty na danych wejściowych użytkownika. Opiera się wyłącznie na zakodowanym na sztywno przedrostku „@tag” i indeksie tablicy. Indeks zawsze być liczbą całkowitą, nie jest generowany przez użytkownika i jest bezpieczny.
Wartości wprowadzone przez użytkownika są nadal umieszczane w parametrach, więc nie ma tam luki.
Edycja:
Pomijając kwestie wstrzykiwania, należy zwrócić uwagę, że konstruowanie tekstu polecenia w taki sposób, aby zawierał zmienną liczbę parametrów (jak wyżej) utrudnia SQL Serverowi korzystanie z buforowanych zapytań. Rezultatem jest to, że prawie na pewno tracisz wartość używania parametrów w pierwszej kolejności (w przeciwieństwie do zwykłego wstawiania ciągów predykatów do samego SQL).
Nie chodzi o to, że buforowane plany zapytań nie są wartościowe, ale IMO to zapytanie nie jest wystarczająco skomplikowane, aby zobaczyć z niego wiele korzyści. Chociaż koszty kompilacji mogą zbliżyć się (lub nawet przekroczyć) koszty wykonania, nadal mówisz o milisekundach.
Jeśli masz wystarczającą ilość pamięci RAM, spodziewam się, że SQL Server prawdopodobnie zapisze również w pamięci podręcznej plan dla typowej liczby parametrów. Przypuszczam, że zawsze można dodać pięć parametrów i niech nieokreślone tagi mają wartość NULL - plan zapytania powinien być taki sam, ale wydaje mi się to dość brzydkie i nie jestem pewien, czy warto by było dokonać mikrooptymalizacji (chociaż na Stack Overflow – może być warto).
Ponadto SQL Server 7 i nowsze będą automatycznie parametryzować zapytania, więc używanie parametrów nie jest tak naprawdę konieczne z punktu widzenia wydajności — jest to jednak krytyczne z punktu widzenia bezpieczeństwa - zwłaszcza w przypadku takich danych wprowadzanych przez użytkownika.