A pagina 84 del Self-Paced Training Kit dell'esame 70-528 di parla dell'oggetto Button (System.Web.UI.WebControls.Button). In particolare, si dice che un pulsante può essere un tradizionale submit button (che è l'impostazione di default), oppure un pulsante di comando. Per creare un Button di quest'ultimo tipo, è necessario impostare le sue proprietà CommandName e CommandArgument. Tuttavia, nel testo manca un passaggio fondamentale: dopo aver settato questa proprietà, si deve gestire l'evento Command e usare le proprietà dell'oggetto CommandEventArgs per sapere qual è il comando da eseguire ed, eventualmente, gli argomenti ad esso associati. Ad esempio, supponiamo che nella pagina ASPX siano stati definiti 3 pulsanti:
<asp:Button ID="Button1" runat="server" Text="Primo pulsante"
CommandName="Primo" />
<asp:Button ID="Button2" runat="server" Text="Secondo pulsante"
CommandName="Secondo" />
<asp:Button ID="Button3" runat="server" Text="Terzo pulsante"
CommandName="Terzo" />
A questo punto si possono registrare gli eventi OnCommand di tutti e 3 i pulsanti sullo stesso metodo Button_Command:
<asp:Button ID="Button1" runat="server" Text="Primo pulsante"
CommandName="Primo" OnCommand="Button_Command" />
<asp:Button ID="Button2" runat="server" Text="Secondo pulsante"
CommandName="Secondo" OnCommand="Button_Command" />
<asp:Button ID="Button3" runat="server" Text="Terzo pulsante"
CommandName="Terzo" OnCommand="Button_Command" />
Infine, nel code-behind della pagina si utilizza la proprietà CommandEventArgs.CommandName per sapere quale pulsante è stato effettivamente premuto:
protected void Button_Command(object sender, CommandEventArgs e)
{
Response.Write("Pulsante premuto: " + e.CommandName);
}
Lo stesso principio di funzionamento vale anche per l'oggetto ImageButton.
I DbDataAdapter di .NET si basano su oggetti di tipo DbCommand per selezionare, aggiornare, aggiungere ed eliminare le informazioni dalla base di dati sottostante. Gli oggetti DbCommand, a loro volta, mantengono un riferimento alla DbConnection che corrisponde all'origine dati in questione. Tale connessione non deve necessariamente essere aperta prima di richiamare i metodi del DbDataAdapter: nel caso in cui sia chiusa quando si eseguono i metodi del DbDataAdapter, viene aperta automaticamente, per poi essere richiusa al termine dell'operazione.
E' possibile verificare questo comportamento con un semplice esempio. Consideriamo il seguente stralcio di codice:
1 SqlConnection db = new SqlConnection(@"Data Source=192.168.0.212\SQLEXPRESS;
2 Initial Catalog=Northwind;Integrated Security=True;");
3 db.StateChange += new StateChangeEventHandler(db_StateChange);
4 db.Open();
5
6 SqlCommand cmd = db.CreateCommand();
7 cmd.CommandType = CommandType.Text;
8 cmd.CommandText = "SELECT * FROM Customers;";
9
10 SqlDataAdapter da = new SqlDataAdapter(cmd);
11 DataSet ds = new DataSet();
12 da.Fill(ds, "Customers");
13
14 private void db_StateChange(object sender, StateChangeEventArgs e)
15 {
16 Response.Write(e.CurrentState + "<br/>");
17 }
In questo caso, la connessione viene manualmente aperta (riga 4) prima di richiamare i metodi del DataAdapter: l'evento StateChange viene generato una sola volta, poiché la connessione, essendo già aperta prima di richiamare il metodo Fill (riga 12), rimane in questo stato anche al termine dell'operazione.
Commentando la riga 4, invece, il comportamento cambia: la connessione verrà aperta per l'esecuzione del metodo Fill (riga 12) e sarà chiusa automaticamente al termine dell'operazione. In altri termini, l'evento StateChange viene generato due volte.