Connessione di un database con ADO.NET (in modalità connessa)
parte II
di Aniello De Simone
In questa seconda lezione vedremo come è possibile scorrere i record che abbiamo ottenuto dopo aver formulato una richiesta al nostro database (sempre biblio), e come modificare tali valori. Questo progetto è un derivato della lezione precedente, per cui andremo a lavorare e modificare la nostra form ed il codice per adattarli alle nostre nuove esigenze. I commenti verranno affiancati solamente alle parti modificate dando per scontato che chi esegue il progetto sia partito dalla lezione precedente.
Il risultato finale sarà un form come in figura 1.
Figura 1
Possiamo notare che sono state aggiunte due caselle di testo, txtOut a sinistra e txtOut1 a destra nella cornice Visualizza, in più ci sono tre Button: Indietro con il simbolo <, Avanti con il simbolo > e il Button Salva.
Quello che vogliamo ottenere è la visualizzazione nelle caselle di testo di un record memorizzato nella tabella Authors del database Biblio, avente un indice che noi indichiamo nella casella txtTrova, poi la possibilità tramite i button Avanti e Indietro di scorrere il record precedente ed il successivo, infine di applicare al database le modifiche che apporteremo al nome dell'autore visualizzato nella casella txtOut1.
Il codice seguente è rimasto uguale:
Imports System.Data.OleDb
Imports System.Windows.Forms
Public Class Form1
Inherits System.Windows.Forms.Form
" Codice generato da Progettazione Windows Form "
'Dichiaro la stringa di connessione,
aggiungere il percorso del db Biblio
Dim ConnString As String
ConnString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source =......."
'Dichiaro la nuova connessione
Dim cn As New OleDbConnection(ConnString)
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
Handles MyBase.Load
If cn.State = ConnectionState.Open Then cn.Close()
End Sub
Private Sub ApriChiudi_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ApriChiudi.Click
If ApriChiudi.Text = "&Connetti" Then
cn.Open()
ApriChiudi.Text = "&Disconnetti"
Else
ApriChiudi.Text = "&Connetti"
cn.Close()
End If
If (cn.State) = ConnectionState.Open Then
MessageBox.Show("Il db adesso è connesso", _
"Attenzione", MessageBoxButtons.OK, _
MessageBoxIcon.Information)
Else
MessageBox.Show("Il db adesso è disconnesso", _
"Attenzione", MessageBoxButtons.OK, _
MessageBoxIcon.Information)
End If
End Sub
Private Sub Esci_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Esci.Click
cn.Close()
End
End Sub
Private Sub Trova_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Trova.Click
Dim testotxt As String = txtTrova.Text
txtOut.Text = ""
txtTrova.Focus()
If cn.State = ConnectionState.Open Then
Nella prossima riga effettuiamo una modifica per eliminare l'inconveniente di ricevere un errore causato dal fatto che non esiste un record nella tabella che ha l'indice da noi specificato. In questo modo la query ci rilascia il record con lo stesso indice od uno subito successivo.
Notiamo nella query l'utilizzo della parola "Distinct": ciò fa si che il risultato sia un solo record, invece dei molti che potrebbero soddisfare la condizione Where.
Dim sql As String
sql="SELECT DISTINCT * FROM authors WHERE au_id >= ?"
Dim cmd As New OleDbCommand(sql, cn)
cmd.Parameters.Add("au_id", testotxt)
Dim dr As OleDbDataReader
OleDbDataReader=cmd.ExecuteReader
dr.Read()
La visualizzazione del resultset avviene stavolta in due caselle di testo in cui la loro proprietà text avrà un valore dato dal datareader (dr) avente un numero progressivo come argomento. Tale argomento nient'altro è che la valorizzazione numerica delle colonne (Au_id e Author)
txtOut.Text = (dr(0))
txtOut1.Text = (dr(1))
If txtOut.Text = "" Then
MessageBox.Show("Nessun autore corrisponde a questo indice", _
"Attenzione!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
dr.Close()
Else
MessageBox.Show("Il db non è ancora connesso", _
"Attenzione", MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
End If
End Sub
Gestiamo ora l'evento click del button Indietro: facciamo doppio click sul pulsante in fase di progettazione e Visual Basic .Net aprirà l'editor con la struttura della sub pronta per essere riempita.
Private Sub Indietro_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Indietro.Click
La parte centrale di questo evento è la query: essa esegue una select tra tutti i record che hanno l'indice minore di quello visualizzato nella txtOut e ne rilascia uno soltanto che , in virtù del fatto che esiste un ordinamento decrescente, è il minore più prossimo. Questo viene fatto per evitare che l'inesistenza di un indice (Au_id) diminuito di una unità (Au_id - 1) generi un errore ovvero, utilizzando termini più appropriati, sollevi un'eccezione.
Dim sql As String
Sql="SELECT TOP 1 * FROM authors WHERE au_id < (" & _
txtOut.Text & ") ORDER BY au_id DESC"
Il codice seguente è stato già visto nella prima lezione ...
Dim cmd As New OleDbCommand(sql, cn)
Dim dr As OleDbDataReader = cmd.ExecuteReader
dr.Read()
E qui riempiamo di nuovo le caselle di testo con i risultati della query :
txtOut.Text = dr(0)
txtOut1.Text = dr(1)
dr.Close()
End Sub
Il codice del pulsante Avanti è quasi uguale al suo complementare, l'unica differenza stà nel fatto che gli indici considerati hanno un valore maggiore, e non minore, di quello preso a paragone e da noi scritto nella casella txtTrova.
Da notare che questa volta non si devono ordinare i dati in modo decrescente .
Private Sub Avanti_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Avanti.Click
Dim Sql As String
Sql="SELECT TOP 1 * FROM authors WHERE au_id > (" & _
txtOut.Text & ") ORDER BY au_id "
Dim cmd As New OleDbCommand(sql, cn)
Dim dr As OleDbDataReader = cmd.ExecuteReader
dr.Read()
txtOut.Text = dr(0)
txtOut1.Text = dr(1)
dr.Close()
End Sub
L'ultima operazione da compiere è quella di gestire l'evento che permetterà di salvare le modifiche che eventualmente apporteremo nella casella di testo dove è visualizzato il nome e cognome dell'autore. Anche in questo caso l'unica difficoltà è quella di creare una stringa contenente una query che esegua l'operazione da noi voluta. In pratica non faremo altro che copiare il contenuto della casella di testo txtOut1 nel database e più precisamente nel record avente indice uguale a quello visualizzato nella casella txtOut.
Da notare che questa operazione deve essere lanciata con il metodo ExecuteNonQuery, a differenza delle query Select che utilizzano il metodo ExecuteReader.
Private Sub Salva_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Salva.Click
Dim sql As String
sql="UPDATE authors SET author= '" & _
txtOut1.Text & "' WHERE Au_id = " & txtOut.Text
Dim cmd As New OleDbCommand(sql, cn)
Dim dr As OleDbDataReader
cmd.ExecuteNonQuery()
dr.Close()
End Sub
End Class
Prima di concludere questa seconda parte vorrei farvi conoscere una scorciatoia che vi servirà per visualizzare il codice in modo ottimale nell' editor. Avete notato che accanto ad ogni struttura tipo sub e function, vb.net si preoccupa di inserire delle caselle conteneti simboli + o - che attivano o disattivano la visualizzazione del codice appartenente a quella parte di programma: sono le caselle per espandere o compimere la struttura. A me capita spesso di voler comprimere tutte le strutture presenti sul listato, questa operazione è possibile in modo automatico digitando "seleziona tutto" e 2 volte ctrl + M. Qesto però comprime un po' troppo, cioè devo poi riaprire anche la struttura del form, per cui credo che la soluzione migliore sia di portare sulla barra degli strumenti un tasto denominato "struttura comprimi alle definizioni" , visualizzabile nel menù personalizza, visibile con il tasto destro sulla barra degli strumenti (Figura 2) e poi selezionando la scheda "comandi" quindi "modifica" (Figura 3).
Figura 2
Figura 3
Spero di essere stato chiaro, un saluto a tutti
Aniello De Simone