Problema risolto, benissimo :)
Adesso prova ad introdurre dei parametri nel tuo SelectCommand.
Sperimenta su una copia della tua pagina, così non rischi di perdere il progresso che hai raggiunto finora. In più, se questa soluzione dovesse sembrarti inultimente complicata, potrai pur sempre gettar via il duplicato e restare con l'attuale soluzione.
Resta comunque un buon esercizio che ti spinge a pensare a come puoi usare il codice T-SQL per lasciar svolgere alcuni compiti a SQL Server, anziché doverlo fare da vb.net.
Parti da un caso facile: facciamo finta che Utenti.Utente sia l'unico campo su cui tu debba cercare. Al SelectCommand dunque accoda una clausola WHERE del tipo Utenti.Utente=@txtcerca. Ecco come diventerebbe il SqlDataSource:
<asp:SqlDataSource ID="SqlDataSourceUtenti" runat="server" ConnectionString="<%$ ConnectionStrings:MiaConnectionString %>"
SelectCommand="SELECT Utenti.IDutente, Utenti.Utente, Ragionerie.Provincia, Utenti.TipoUtente FROM Utenti INNER JOIN Ragionerie ON Utenti.IDragioneria = Ragionerie.IDragioneria WHERE Utenti.Utente=@txtcerca">
<SelectParameters>
<asp:ControlParameter ControlID="Txtcerca" PropertyName="Text" Name="txtcerca" />
</SelectParameters>
</asp:SqlDataSource>
Ho dovuto aggiungere anche un ControlParameter, così che il segnaposto @txtcerca che ho usato nella query venga poi sostituito dalla proprietà Text di Txtcerca.
Avendo reso la query parametrica, non bisogna più preoccuparsi di SQL Injection perché eventuali combinazioni "malevole" di caratteri verranno rese innocue.
Giulypop ha scritto:
non saprei come associare l'evento del button "cerca"
Non associarlo, anzi, elimina del tutto la funzione Btncerca_Click. Il nostro scopo è fare tutto in maniera dichiarativa quindi il codice che avevi messo all'interno di quella funzione andremo presto a "convertirlo" in codice SQL. Fai in modo che Btncerca sia un semplice asp:Button, il cui evento click
non è gestito. Questo bottone deve solo servire a causare il postback della pagina dopo che l'utente ha digitato qualcosa in Txtcerca, in modo che il set di risultati possa essere rigenerato.
Quindi lancia la pagina, digita il nome di un utente nella textbox, clicca il bottone e vedrai apparire le sue righe nella GridView.
Adesso però già sorge un problema. La WHERE Utenti.Utente=@txtcerca non mi consentirà
mai di visualizzare tutti i risultati. Invece magari voglio che se l'utente non digita nulla, non avvenga alcun filtraggio.
Allora possiamo alterare leggermente la WHERE per fare in modo che questo caso sia gestito:
WHERE Utenti.Utente=COALESCE(@txtcerca, Utenti.Utente)
e al ControlParameter aggiungere l'attributo ConvertEmptyStringToNull="true"
Quello che succederà è questo: se l'utente non digita nulla, alla query verrà passato un valore null per il parametro @txtcerca. La funzione
COALESCE restituirà il primo parametro (@txtcerca) purché non sia null ma, dato che lo è, allora restituirà il secondo (Utenti.Utente).
Quindi, nel caso in cui non si digiti alcun testo, il valore di Utenti.Utente verrebbe confrontato con sé stesso e ciò produrrebbe una condizione sempre verificata per ogni record. In sintesi: se non si digita nulla, i risultati appariranno tutti.
Ora hai un'ultima complicazione: fare in modo che la sola textbox Txtcerca possa cercare su più campi, in base al valore della DropDownList.
Nel consegue che il primo membro dell'uguaglianza (WHERE Utenti.Utente=) deve variare in base al valore DropDownCerca. Per questo puoi usare un'istruzione
CASE e introdurre un secondo parametro per DropDownCerca.
WHERE (CASE @dropdowncerca WHEN '1' THEN Utenti.Utente ELSE Ragionerie.Provincia END)=...
Quando il parametro @dropdowncerca avrà il valore di '1', allora il campo che entra in gioco nell'uguaglianza sarà Utenti.Utente, altrimenti sarà Ragionerie.Provincia.
Questo richiede che sia presente anche il secondo ControlParameter.
<asp:ControlParameter ControlID="DropDownCerca" PropertyName="SelectedValue" Name="dropdowncerca" />
Sembra complicato fin qui? Decidi tu se vale la pena di usare questo sistema per evitare ripetizioni di codice SQL nel codefile.
Certamente il SelectCommand diventa un po' meno leggibile per via delle istruzioni COALESCE e CASE che sono state introdotte. Ancor più perché il campo su cui cercare è menzionato in entrambi i membri dell'uguaglianza. Se prima avevi:
Utenti.Utente=COALESCE(@txtcerca, Utenti.Utente)
Ora dovrai fare:
WHERE (CASE @dropdowncerca WHEN '1' THEN Utenti.Utente ELSE Ragionerie.Provincia END) = COALESCE(@txtcerca, (CASE @dropdowncerca WHEN '1' THEN Utenti.Utente ELSE Ragionerie.Provincia END))
yikes! Ma per fortuna in Sql Server puoi usare una
Common Table Expression per restituire leggibilità alla query ed evitare ripetizioni. Ecco l'esempio completo.
<asp:SqlDataSource ID="SqlDataSourceUtenti" runat="server" CancelSelectOnNullParameter="false"
SelectCommand="WITH MiaTab AS( SELECT Utenti.IDutente, Utenti.Utente, Ragionerie.Provincia, Utenti.TipoUtente, (CASE @dropdowncerca WHEN '1' THEN Utenti.Utente ELSE Ragionerie.Provincia END) as CampoRicerca FROM Utenti INNER JOIN Ragionerie ON Utenti.IDragioneria = Ragionerie.IDragioneria) SELECT * FROM MiaTab WHERE CampoRicerca=COALESCE(@txtcerca, CampoRicerca)"
ConnectionString="<%$ ConnectionStrings:MiaConnectionString %>">
<SelectParameters>
<asp:ControlParameter ControlID="Txtcerca" PropertyName="Text" Name="txtcerca" ConvertEmptyStringToNull="true" />
<asp:ControlParameter ControlID="DropDownCerca" PropertyName="SelectedValue" Name="dropdowncerca" ConvertEmptyStringToNull="true" />
</SelectParameters>
</asp:SqlDataSource>
ciao
Modificato da BrightSoul il 18 marzo 2013 22.30 -