Query parametrizzate con condizioni LIKE e IN

Le query parametrizzate in .Net hanno sempre questo aspetto negli esempi:

SqlCommand comm = new SqlCommand(@" SELECT * FROM Products WHERE Category_ID = @categoryid ", conn); comm.Parameters.Add("@categoryid", SqlDbType.Int); comm.Parameters["@categoryid"].Value = CategoryID; 

Ma mi imbatto in un muro di mattoni cercando di fare quanto segue:

 SqlCommand comm = new SqlCommand(@" SELECT * FROM Products WHERE Category_ID IN (@categoryids) OR name LIKE '%@name%' ", conn); comm.Parameters.Add("@categoryids", SqlDbType.Int); comm.Parameters["@categoryids"].Value = CategoryIDs; comm.Parameters.Add("@name", SqlDbType.Int); comm.Parameters["@name"].Value = Name; 

Dove

  • CategoryIDs è un elenco di numeri separati da virgole “123,456,789” (senza virgolette)
  • Il nome è una stringa, possibilmente con virgolette singole e altri caratteri non validi

Qual è la syntax giusta per questo?

Diciamo che hai gli ID di categoria in un array intero e Name è una stringa. Il trucco è creare il testo del comando per consentire di inserire tutti gli ID di categoria come parametri individuali e build la corrispondenza fuzzy per il nome. Per fare il primo, usiamo un ciclo per build una sequenza di nomi di parametri da @ p0 a @ pN-1 dove N è il numero di ID di categoria nell’array. Quindi costruiamo un parametro e lo aggiungiamo al comando con l’id della categoria associata come valore per ogni parametro denominato. Quindi usiamo la concatenazione sul nome nella query stessa per consentire la ricerca fuzzy sul nome.

 string Name = "someone"; int[] categoryIDs = new int[] { 238, 1138, 1615, 1616, 1617, 1618, 1619, 1620, 1951, 1952, 1953, 1954, 1955, 1972, 2022 }; SqlCommand comm = conn.CreateCommand(); string[] parameters = new string[categoryIDs.Length]; for(int i=0;i 

Questa è una query completamente parametrizzata che dovrebbe rendere felice il tuo DBA. Ho il sospetto che dal momento che questi sono numeri interi, anche se non sarebbe un grosso rischio per la sicurezza solo build il testo del comando direttamente con i valori, mentre si sta ancora parametrizzando il nome. Se gli ID di categoria sono in un array di stringhe, basta dividere l'array su virgole, convertirli ciascuno in un numero intero e memorizzarlo nell'array intero.

Nota: io dico array e lo uso nell'esempio, ma dovrebbe funzionare per qualsiasi raccolta, anche se la tua iterazione probabilmente differirà.

Idea originale da http://www.tek-tips.com/viewthread.cfm?qid=1502614&page=9

Hai bisogno di “%” nel valore del parametro sql.

 SqlCommand comm = new SqlCommand("SELECT * FROM Products WHERE Category_ID IN (@categoryid1, @categoryid2) OR name LIKE @name", conn); comm.Parameters.Add("@categoryid1", SqlDbType.Int); comm.Parameters["@categoryid1"].Value = CategoryID[0]; comm.Parameters.Add("@categoryid2", SqlDbType.Int); comm.Parameters["@categoryid2"].Value = CategoryID[1]; comm.Parameters.Add("@name", SqlDbType.Int); comm.Parameters["@name"].Value = "%" + Name + "%"; 

Questo approccio non funzionerà. Periodo.

La clausola IN si aspetta un elenco di parametri, quindi quando si associa un parametro ad esso, si ha la possibilità di passare un valore.

Costruisci la stringa di istruzioni dynamicmente, con l’ammontare esatto dei singoli segnaposti della clausola IN che intendi trasferire, quindi aggiungi parametri e associa i valori a loro in un ciclo.

non sono sicuro se questo è il modo giusto, ma è un modo in cui l’ho fatto nel Prima

lista templist = nuova lista

comm.Parameters.Add (“@ categoryids”, SqlDbType.varchar); comm.Parameters [“@ categoryids”]. value = string.join (“,”, templist.toarray ())