Le avventure in VB.Net di un principiante ex-VB6 - 2
a cura di Oscar Zanin e Diego Cattaruzza (requisiti: Visual Basic Express e SqlServer Express)

Premessa
Nell'articolo precedente è stato presentato il progetto di questa serie di articoli e si è impostato l'ambiente di programmazione, visual studio e sqlserver, in cui esso verrà sviluppato.
In questo articolo verrà creato e illustrato il database di esempio, con qualche informazione teorico-pratica suggerita dall'argomento.

Creazione attraverso il Management del database di esempio
Prima di tutto creiamo la cartella GesImp che dovrà contenere il progetto e in essa la sottocartella Risorse, destinata ai file di database.

Nella colonna di sinistra del Management clicchiamo con il tasto destro sulla voce Database e quindi su Nuovo database.
Nel form che appare impostare come nome APP-P (acronimo di Articolo Primi Passi - Principiante) e nella griglia sottostante indicare come percorso la sottocartella Risorse appena creata.
Ora abbiamo il nostro database vuoto.

Tipi di dato
Prima di iniziare a creare le tabelle credo sia utile fare qualche riflessione sui tipi dei dati. Per chi arriva come me da Access è necessario comprendere cosa cambia rispetto a SQL Server e cosa è rimasto sostanzialmente immutato.

A parte, in Tabella1, ho compilato l'elenco dei tipi di dato messi a disposizione da SQL Server, divisi opportunamente per categoria, con relativa descrizione. In realtà con SQL 2008 mi sembra che siano stati aggiunti altri tipi di dati ma, visto che il mio approccio a SQL Server è ancora troppo recente, non voglio cimentarmi in un aggiornamento dell'elenco sottostante.

Mi sembra interessante riportare anche due tabelle che ho trovato durante le mie ricerche. La prima riporta le equivalenze fra i tipi di Access e quelli di SQL Server. La seconda, oltre a fornire lo stesso servizio in modo più schematico, mappa i tipi fra Visual Basic 6, Access, SQL Server e il .NET Framework.
Sono in inglese, ma il tutto è ugualmente facilmente comprensibile, a chi ne ha una minima infarinatura.
Per tutte e tre le tabelle purtroppo non ricordo le fonti, pertanto mi scuso con i creatori se non li cito.

Creazione Tabelle
Apriamo la struttura ad albero dei Database, quella del database APP-P, quindi clicchiamo con il tasto destro su Tabelle selezionando poi Nuova tabella.
Siamo entrati nella progettazione della nuova tabella.
Creiamo i campi seguenti:

Nome Tipo Consenti
valori
Null
Stato varchar(30) No
Modifica bit Si

Il campo Stato è chiave univoca. La chiave univoca di una tabella si crea selezionando il o i campi necessari e cliccando sull'apposito pulsante "Imposta chiave primaria", contraddistinto dall'icona a forma di chiave, posizionato in alto sopra la colonna Esplora oggetti.

Devo aprire una piccola parentesi per spiegare il significato che avrà il campo Modifica. Questo campo me lo porto dietro da Visual Basic 6 e Access. Lo uso per gestire la concorrenza durante l'uso simultaneo del programma da parte di più utenti. Non ho mai voluto usare i blocchi di record, un po' perché complicati da gestire, un po' perché sconsigliati da molti. Ho optato quindi per una gestione "artigianale" della concorrenza.
In pratica, quando un utente entra in modifica su un record imposto a vero il campo Modifica dello stesso e lo riporto a falso quando lo stesso utente conferma l'operazione oppure l'annulla. Nel frattempo il record è bloccato. In Visual Basic 6 in realtà lanciavo un semplice avviso a video senza bloccare ma in NET ho preferito bloccarlo proprio. Tutte le form che creo hanno comunque in dotazione un pulsante di emergenza per lo sblocco: se per caso va via la corrente mentre un record è in modifica e il capo rimane impostato vero.

La prima tabella è fatta. Si può salvarla e nominarla Stati.
Questa è la procedura standard da seguire per ciascuna delle tabelle di cui si illustra la struttura, prima di salvare e dare il nome.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Banca varchar(50) No
Agenzia varchar(50) No
ABI varchar(10) Si
CAB varchar(10) Si
Swift varchar(15) Si
Indirizzo varchar(50) Si
CAP varchar(5) Si
Citta varchar(50) Si
Provincia varchar(4) Si
Stato varchar(30) Si
Telefono varchar(25) Si
Fax varchar(25) Si
Modifica bit Si

La chiave univoca è rappresentata dalla coppia di campi Banca e Agenzia.

([Diego]: avrei preferito un campo Int di nome IDbanca, come altrettanto avrei preferito un campo IDstato per la tabella Stati. Un indice primario su un campo di testo è particolarmente costoso e certamente meno efficiente di uno su un campo di tipo 'nativo' come il tipo Intero Lungo.
Inoltre, ABI e CAB hanno una lunghezza fissa minore di 10. Volendo si potrebbe normalizzare ulteriormente per province e città)

Avendo già creato in precedenza la tabella Stati e avendo questa tabella, fra gli altri, il campo Stato possiamo creare una relazione fra le due tabelle. Il rapporto fra Stati e Banche sarà naturalmente di uno a molti.
Per creare la relazione, essendo ancora in progettazione della tabella Banche, clicchiamo sul relativo pulsante "Relazioni" contraddistinto dall'icona con tre form collegate fra loro, sempre posizionato sopra la colonna Esplora oggetti.

Appare un form denominato "Relazioni chiave esterne". Selezioniamo la proprietà "Specifica tabelle e colonne", quindi clicchiamo sul pulsante con i tre puntini.
Apparirà un nuovo form denominato "Tabelle e colonne". Nell'elenco a tendina "Tabella di chiave primaria" selezioniamo la tabella Stati; nella griglia sottostante selezioniamo il campo Stato sia in corrispondenza della tabella Stati che di quella Banche.
Come avrete notato il nome della relazione è stato costruito in modo appropriato automaticamente.

Una scelta che avevo già fatto in Access è quella relativa agli automatismi che sia Access che SQL Server mettono a disposizione nel momento in cui si crea una relazione fra tabelle. Sto parlando del lasciar verificare la congruenza dei dati al database. Come avrete notato, fra le altre ci sono tre proprietà impostate a Si che io voglio portare a No, ovvero:

Inoltre richiamo l'attenzione sulla proprietà Specifica INSERT e UPDATE che a sua volta si suddivide in Regola di aggiornamento e regola di eliminazione. Entrambi li lasceremo impostati a "Nessuna azione". A cosa servono? Riporto anche qui da TechNet in quanto mi sembra ben spiegato:

Vi starete dicendo ... "ma così hai eliminato tutti gli automatismi". E' vero! Tutte queste cose preferisco controllarmele da codice. Non voglio che "qualcun'altro" lo faccia per me. Come scrivevo nell'introduzione sono uno al quale piace avere pieno controllo del flusso del codice, anche se questo va a penalizzarmi costringendomi a scrivere del codice in più.

([Diego]: con SqlServer ci si può ragionevolmente fidare, di alcuni automatismi, ma in questo caso l'impostazione a 'nessuna azione' ci conviene.
Questa struttura riprende, evidentemente, una struttura già sperimentata su un database Access.
Si vedrà nel seguito se ci riesce di applicare modifiche alla struttura del database. Poiché è una situazione abbastanza 'normale', esamineremo le problematiche sovvenienti al momento giusto.
Per il momento mi limiterò a fare qualche critica, quando è il caso)

In tutte le tabelle che seguiranno queste proprietà andranno impostate in questo modo.
Confermiamo l'operazione e salviamo la relazione.
Si può ora salvare la tabella e nominarla Banche.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Pagamento varchar(50) No
Fine_mese bit Si
Giorno_fisso smallint Si
Appoggio_banca bit Si
Modifica bit Si

La chiave univoca è il campo Pagamento ([Diego]: anche qui è preferibile una chiave IDpagamento).
Salvare la tabella e nominarla Pagamenti.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Pagamento varchar(50) No
Scadenza smallint No
Percentuale real No

La chiave univoca è rappresentata dalla coppia di campi Pagamento e Scadenza ([Diego]: così non si sfrutta bene le capacità di sqlserver: è molto più performante un indice su due Int che su qualsiasi altro tipo, se poi sono due tipi diversi tra loro...).
Questa tabella, come facilmente si può intuire, è legata con la precedente da una relazione Master/Detail. Creiamo la relazione indicando come campo comune alle due tabelle il campo Pagamento.
Salvare la tabella e nominarla Pagamenti_dettaglio.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Codice int No
Nome varchar(50) No
Indirizzo varchar(50) No
CAP varchar(5) Si
Citta varchar(50) No
Provincia varchar(4) Si
Stato varchar(30) Si
Telefono varchar(25) Si
Fax varchar(25) Si
Cellulare varchar(25) Si
Telefono1 varchar(25) Si
Fax1 varchar(25) Si
Cellulare1 varchar(25) Si
Codice_fiscale varchar(16) Si
Partita_iva varchar(13) Si
Pagamento varchar(50) Si
Banca varchar(50) Si
Agenzia varchar(50) Si
ABI varchar(10) Si
CAB varchar(10) Si
NumCC varchar(15) Si
TitCC varchar(30) Si
CIN char(1) Si
IBAN varchar(35) Si
Internet varchar(50) Si
EMail varchar(50) Si
Riclis real Si
Oratecs decimal(13, 2) No
Oratecsstr decimal(13, 2) No
Oratec decimal(13, 2) No
Oratecstr decimal(13, 2) No
Oraaiu decimal(13, 2) No
Oraaiustr decimal(13, 2) No
Modifica bit Si

La chiave univoca è il campo Codice ([Diego]: perché mai un nome così generico? Io l'avrei chiamato IDcliente. Inoltre, mi danno fastidio i nomi non autodescrittivi come Riclis e Oraxxx).
Vanno create le relazioni fra questa tabella e alcune di quelle create in precedenza e più nello specifico (rapporto uno a molti):

Salvare la tabella e nominarla Clienti.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Codice int No
Riferimento varchar(50) No
Telefono varchar(25) Si
Fax varchar(25) Si
Cellulare varchar(25) Si
EMail varchar(50) Si

La chiave univoca è rappresentata dalla coppia di campi Codice e Riferimento ([Diego]: se uno non sa a priori a cosa si riferisce codice, che ne può capire? se il campo si chiamasse IDcliente, sarebbe chiaro, anche fra tre anni).
Questa tabella è legata con la tabella Clienti da una relazione Master/Detail. Creiamo la relazione indicando come campo comune alle due tabelle il campo Codice.
Salvare la tabella e nominarla Clienti_riferimenti.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Codice int No
Nome varchar(50) No
Indirizzo varchar(50) No
CAP varchar(5) Si
Citta varchar(50) No
Provincia varchar(4) Si
Stato varchar(30) Si
Telefono varchar(25) Si
Fax varchar(25) Si
Cellulare varchar(25) Si

La chiave univoca è rappresentata dai campi Codice ([Diego]: visto? un campo omonimo di un altro. Non ci sarebbe ambiguità se ognuno fosse 'chiaro', come IDsede, per esempio qui), Nome ([Diego]: altro nome generico, mentre con un minimo di fantasia si può denominare il campo Sede) e Citta.
Questa tabella è legata con la tabella Clienti da una relazione Master/Detail.
Creiamo la relazione indicando come campo comune alle due tabelle il campo Codice.
Salvare la tabella e nominarla Clienti_sedi.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Codice int No
Nome varchar(50) No
Indirizzo varchar(50) No
CAP varchar(5) Si
Citta varchar(50) No
Provincia varchar(4) Si
Stato varchar(30) Si
Telefono varchar(25) Si
Fax varchar(25) Si
Cellulare varchar(25) Si
Telefono1 varchar(25) Si
Fax1 varchar(25) Si
Cellulare1 varchar(25) Si
Codice_fiscale varchar(16) Si
Partita_iva varchar(13) Si
Pagamento varchar(50) Si
Banca varchar(50) Si
Agenzia varchar(50) Si
ABI varchar(10) Si
CAB varchar(10) Si
NumCC varchar(15) Si
TitCC varchar(30) Si
CIN char(1) Si
IBAN varchar(50) Si
Internet varchar(50) Si
EMail varchar(50) Si
Modifica bit Si

La chiave univoca è il campo Codice ([Diego]: IDfornitore..., inoltre, a me danno fastidio i nomi di capo non autodescrittivi, come NumCC e TitCC).
Vanno create le relazioni fra questa tabella e alcune di quelle create in precedenza:

Salvare la tabella e nominarla Fornitori.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Codice int No
Riferimento varchar(50) No
Telefono varchar(25) Si
Fax varchar(25) Si
Cellulare varchar(25) Si
EMail varchar(50) Si

La chiave univoca è rappresentata dalla coppia di campi Codice e Riferimento.
Questa tabella è legata con la tabella Fornitori da una relazione Master/Detail. Creiamo la relazione indicando come campo comune alle due tabelle il campo Codice.
Salvare la tabella e nominarla Fornitori_riferimenti.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
UM varchar(5) No
Modifica bit Si

La chiave univoca è il campo UM.
Salvare la tabella e nominarla Unita_di_misura.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Codice varchar(20) No
Prodotto varchar(50) No
UM varchar(5) No
Preacq decimal(13, 2) Si
Preven decimal(13, 2) Si
Quantita float Si
Acquisto bit Si
Vendita bit Si
Stampa bit Si
Modifica bit Si

La chiave univoca è il campo Codice ([Diego]: IDprodotto, nomi non autodescrittivi come Preacq e Preven).
Va creata la relazione (uno a molti) fra questa tabella e la tabella Unita_di_misura:

Salvare la tabella e nominarla Prodotti.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Data smalldatetime No
Numero varchar(20) No
Codfor int No
Fornitore varchar(50) No
Modifica bit Si

La chiave univoca è rappresentata dai campi Data, Numero e Codfor.
Va creata la relazione fra questa tabella e la tabella Fornitori (rapporto uno a molti):

  1. Fornitori / Carico_magazzino
    Aprire in modifica (versione 2005) o in progettazione (versione 2008) la tabella Fornitori, visualizziamo le relazioni e impostiamo come campo della tabella Carico_magazzino, Codfor e come campo della tabella Fornitori, Codice ([Diego]: se il campo della tabella Fornitori fosse denominato IDfornitore, non ci sarebbe alcun problema di ambiguità, non ci si troverebbe a dover inventare un nome come CodFor).

Salvare la tabella e nominarla Carico_magazzino.

Nuova Tabella. I campi da creare sono i seguenti:

Nome Tipo Consenti
valori
Null
Data smalldatetime No
Numero varchar(20) No
Codfor int No
Codice varchar(20) No
Prodotto varchar(50) No
UM varchar(5) No
Quantita float No
Preacq decimal(13, 2) No
Preven decimal(13, 2) No

La chiave univoca è rappresentata dai campi Data, Numero, Codfor e Codice (prodotto) ([Diego]: se si fosse chiamato IDprodotto, non ci sarebbe stato bisogno di specificare).
Deve essere creata la relazione Master/Detail con la tabella Carico_magazzino. Creiamo la relazione indicando come campi comuni alle due tabelle Data, Numero e Codfor.
Inoltre va creata la relazione fra questa tabella e la tabella creata in precedenza Prodotti (rapporto uno a molti):

Salvare la tabella e nominarla Carico_prodotti.

Conclusione
Abbiamo terminato di creare la base dati necessaria al nostro esempio.
Nel prossimo articolo della serie passeremo finalmente al Visual Basic e alla creazione del nuovo progetto.