ACCESSO AI DATI CON ADO.NET

CREARE UN DATABASE SQLLITE

NET CORE

È arrivato il momento di utilizzare un database relazionale, e se usiamo un database è perché vogliamo persistere i dati della nostra applicazione in maniera durevole. Per questo progetto utilizzeremo SQLite che è una tecnologia molto snella, basato su file non richiede l’installazione di alcun prerequisito. Useremo un approccio database-first prima creeremo il database e le tabelle poi ci andremo a collegare con il codice C#.

IL DATABASE MYCOURSE.DB

Il database deve rimanere privato, nessuno se lo deve scaricare quindi il posto migliore per posizionarlo è in una nuova cartella sotto la Root chiamata Data. Tutti i comandi per creare le tabelle e inserire dei dati fittizi li trovi sotto la directory docs/ddl. Sotto la cartella Data crea un file e chiamalo MyCourse.db, procurati un’estensione se usi Visual Studio Code o un plugin che gestisca script SQL di SQLite oppure procurati un programma che gestisca database SQLite, in rete ne trovi molti.

ORGANIZZARE IL MODEL IN SERVIZI APPLICATIVI E INFRASTRUTTURALI

In precedenza, abbiamo utilizzato una classe CourseService che era un servizio applicativo che ci restituiva delle informazioni sui corsi. Ora che abbiamo dei dati nel database SQLite il CourseService non ci serve più. Adesso andremo a crearci un nuovo servizio applicativo che stavolta usa ADO.NET. Un servizio Applicativo ha la responsabilità di sapere cosa estrarre, mentre invece come ci si collega al Database e come si estraggono le informazioni è una responsabilità del servizio infrastrutturale. Il nostro servizio applicativo avrà una dipendenza da questo servizio infrastrutturale.

AdoNetCourseService

Vediamo l’interfaccia.

IDatabaseAccessor

LA GERARCHIA DEI COMPONENTI CREATI

Abbiamo creato prima una interfaccia ICourseService e abbiamo fatto l’injection dell’implementazione concreta AdoNetCourseService. Questo nello strato applicativo. Nello strato infrastrutturale abbiamo creato l’interfaccia IDatabaseAccessor e abbiamo iniettato la dipendenza SqliteDatabaseAccessor.

Architettura

Questo è il file Startup.cs

CONOSCERE LE CLASSI DI ADO.NET

ADO.NET è una tecnologia tradizionale che ha tanti anni sulle spalle, ma che è stata introdotta in .NET CORE per via della sua stabilità e versatilità. È basato su provider e può funzionare con tanti DBMS, basta procurarsi i file da NuGet. Se scarichiamo il provider per SQLite avremo una classe SqliteConnection, cambiando provider per MySQL avremo MySQLConnection etc.

ADO.NET

Queste sono alcune classi, che conosceremo meglio in seguito, fornite dal provider per SQLite, provider sviluppato da Microsoft.

SQLite

Vediamo le interfacce che forniscono un accoppiamento debole per il provider SQLite.

Interfacce

IL FUNZIONAMENTO DI ADO.NET

Vediamo con un video e con la spiegazione di ogni animazione come funziona ADO.NET.

Per prima cosa ci creiamo un oggetto SqliteConnection, e invochiamo il suo metodo open per aprire la connessione. In realtà la connessione non viene aperta in questo momento, anche perché se stiamo usando ad esempio SQLServer il database potrebbe risiedere su un altro server, quindi aprire la connessione significa, creare un socket TCP, se la connessione è cifrata c’è tutto il protocollo TLS, vi è tutta la fase di autenticazione. Insomma, ci sono alcuni passi da compiere che nel complesso richiedono decine di millisecondi. ADO.NET introduce un organo chiamato Connection Pool che crea un certo numero di connessioni proattive prima.

IL CONNECTION POOL

Quando viene invocato il metodo Open in realtà è il Connection Pool che fornisce la connessione già pronta all’uso. Questo aumenta di molto l’efficienza. Una volta che la connessione è stata aperta ci creiamo il nostro oggetto SqliteCommand per, ad esempio, estrarre tutti i corsi dal database. Grazie al metodo ExecuteReader() invierà il comando di SELECT al database. Il database estrarrà le righe che attenzione ancora sono lato server, non sono nella memoria dell’applicazione. Ed è qui che entra in gioco il metodo ExecuteReader() che ci restituirà un oggetto SqliteDataReader che grazie al suo metodo Read() potrà estrarre dal database una riga alla volta e trasferire l’informazione nella memoria dell’applicazione. Una volta letti tutti i risultati, il metodo Read() restituirà false, possiamo utilizzare il metodo Dispose() sulla connessione per chiuderla, anche se in realtà si tratta di restituire quella connessione al Connection Pool.

A sinistra troviamo tutti gli oggetti che hanno bisogno di una connessione attiva con il database per poter funzionare, a destra due componenti che possono lavorare in modalità disconnessa.

Classi connesse e disconnesse

USARE LE CLASSI DI ADO.NET PER ACCEDERE AL DATABASE

Vediamo finalmente dopo aver fatto una panoramica su ADO.NET come viene messa in pratica la teoria, assicurandoci come prima cosa che le connessioni vengano chiuse dopo averle utilizzate. Se vi è una cattiva gestione di questo aspetto le connessioni attive fornite dal Connection Pool di ADO.NET che non sono infinite potrebbero esaurirsi e causare un errore a runtime.

Connessioni

Con lo using anche se si verifica un’eccezione abbiamo la garanzia che la connessione al database venga chiusa.

using

STRUTTURA DI UN DATASET E UTILIZZO NEL CODICE

Vediamo la struttura del dataset e come è stato utilizzato nel codice.

SqliteDataBaseAccessor
DataSet

LEGGERE UN DATASET E MAPPARE LE INFORMAZIONI SU UN VIEWMODEL

Torniamo al servizio applicativo e vediamo come si leggono le informazioni da un DataSet per mapparle nel ViewModel.

AdoNetCourseService_2

Vediamo il ViewModel.

CourseViewModel

LINK AL CODICE SU GITHUB

GITHUB

Scaricare il codice della sezione10 o clonare il repository GITHUB per avere a disposizione tutte le sezioni nel tuo editor preferito. IL DETTAGLIO DEL CORSO ANCORA NON E’ STATO IMPLEMENTATO.