[Pensate pericolose] Costruzione degli SQL dinamici

Nel mezzo dell'implementazione della solita CRUD e dei soliti metodi di ricerca mi sono messo ad osservare quanto poco leggibile potrebbe diventare il codice quando il metodo di ricerca potrebbe prevedere alcuni (in numero almeno maggiore di 2) parametri opzionali. In tal caso sia che usiamo una store procedure sia che usiamo SQL da codice ci troviamo ad avere a che fare con la costruzione dinamica dell'SQL. Nell'esempio che posto qui sotto userò un caso ad un solo parametro... ok il numero dei parametri è minore di 2 ma per chi ha presente il problema la cosa dovrebbe risultare comunque famigliare.

Ecco qui un esempio del metodo classico e sotto la pensara della domenica... come al solito questa è un idea di cui non mi assumo le responsabilità e va presa "AS IS". Io non l'ho mai usato anche perchè l'ho pensata 5 minuti fà :-p Se la cosa potrebbe avere il suo perchè non lo so, per ora persisto l'idea qui poi si vedrà :-p

[Metodo classico]

const string SQl_SELECT = "SELECT * FROM Customers";
[...]
public static CustomersCollection Retrieve(string companyNameLike)
{
 CustomersCollection customers = new CustomersCollection();
 SqlCommand cmd = new SqlCommand();
 
 [...]
 StringBuilder sql = new StringBuilder(SQL_SELECT);
 
 if(companyNameLike != string.Empty){
  sql.Append(" WHERE companyName LIKE @companyNameLike");
  cmd.Parameters.Add("@companyNameLike", string.Concat(companyNamelike, "%")); 
 }
 
 cmd.CommandText = sql.ToString();  
 [...]
 return customers;
}

[La pensata della domenica]
Comando un po più ostico da leggere ma codice più _snello_.

const string SQl_SELECT = "SELECT * FROM Customers WHERE (@companyNameLike = '%' OR companyName LIKE @companyNameLike)";
[...]
public static CustomersCollection Retrieve(string companyNameLike)
{
 CustomersCollection customers = new CustomersCollection();
 
 SqlCommand cmd = new SqlCommand(); 
 cmd.Parameters.Add("@companyNameLike", string.Concat(companyNamelike, "%"));
  
 cmd.CommandText = SQl_SELECT;  
 [...]
 return customers;
}

Cambiano le preformance? a okkio non sembra, facendo analizzare la cosa dal Query Analizer le sfide sono:

1a) SELECT * FROM dbo.Customers
vs
2a) SELECT * FROM Customers WHERE ('%' = '%' OR companyName LIKE '')

e (esempio di filtro per nome compagnia che inizia per 'B')

1b) SELECT * FROM dbo.Customers where companyName like 'B%'
vs
2b) SELECT * FROM Customers WHERE ('B%' = '%' OR companyName LIKE 'B%')

1b) e 2b) sembrano avere lo stesso costo... mentre 2a) sembra costare meno di 1a), la cosa mi pare un po strana... su questo è meglio indagare :o

Per chi invece fosse ancora titubante sull'uso dei parametri, potrebbe essere utile spulciare da questo thread i plurimotivi del perchè è meglio usare i parametri invece della concatenazione di stringhe, "Apice in Sql".

«febbraio»
domlunmarmergiovensab
303112345
6789101112
13141516171819
20212223242526
272812345
6789101112