Introduzione a LiteDB

Un database “Leggero”

In alcune situazioni può non servirci un classico SQL Server o MySql per memorizzare i nostri dati.  Ci tornerebbe utile un database NoSql che fosse veloce, con poca (o nessuna) configurazione da effettuare e possibilmente utilizzabile anche su dispositivi mobile. Una buona soluzione a questa necessità può essere LiteDb.

LiteDb è un database NoSql, embedded e zero-configuration che potrebbe rivelarsi uno strumento comodissimo durante i nostri sviluppi.

Prima di vederne il funzionamento, cerchiamo di capire cosa siano tutti questi appellativi che lo accompagnano.

NoSql

Con NoSql, il cui acronimo sta per “Not only Sql”, si identificano tutti quei Database Management System (DBMS) che non si basano sul classico modello dati relazionale (come fanno invece, ad esempio, SQL Server, Oracle, PostgreSQL) e che quindi non hanno SQL come linguaggio di interrogazione della base dati.

Negli anni NoSql è diventato un vero e proprio movimento, che ha raccolto molti seguaci (tra i quali anche big dell’IT come Google ed Amazon). A differenza di quello che si potrebbe pensare, colore che utilizzano NoSql non sono contrari all’utilizzo di database relazionali; il loro punto di vista è molto semplice e si esplica nell’idea che, alle volte, potrebbe risultare una forzatura l’utilizzo di strutture relazionali, mentre in altri casi potrebbe essere la soluzione vincente.

Embedded

È una tipologia di database sviluppato per poter essere integrato all’interno della nostra applicazione. Le funzionalità del database diventano parte integrante dell’applicazione stessa.

Zero-configuration

Quest’ultimo punto è abbastanza semplice: come vedremo successivamente, non ci sarà bisogno di alcuna configurazione iniziale.

Database relazionali Vs NoSQL

Per capire a pieno le differenze tra essi,  faremo un confronto tra un database relazionale e uno NoSql.

Row vs Document

La prima differenza risiede in  cosa viene memorizzato. Un database relazionale storicizza i dati in colonne, mentre uno NoSql storicizza le entità come documenti, il cui contenuto è in formato JSON.

Column vs Property

Per descrivere le righe in un database relazionale dobbiamo utilizzare le colonne, mentre nel mondo NoSql i documenti sono composti da proprietà.

Schema vs Schemaless

Nei database relazionali ogni tabella è descritta da uno schema fisso che descrive le colonne e i tipi dato ed ogni entità è costretta a seguire tale schema. Al contrario, nella metodologia NoSql, non esiste uno schema da seguire e ogni documento può essere strutturato in maniera differente.

Come è possibile vedere nell’esempio qui sopra, se volessimo aggiungere un’ulteriore colonna di tipo Date, nel caso di database relazionale saremmo costretti a modificare la struttura del database tenendo in considerazione anche il fatto che questa nuova colonna dovrà essere retroattiva in quanto i dati già inseriti dovranno comunque gestire correttamente questa nuova colonna. Quindi dovremmo inserire il valore della data per ogni riga già presente, oppure utilizzare un tipo di dato nullable in modo da non inserire questa informazione per i dati già esistenti.

In caso di database NoSql, invece, non essendoci uno schema predefinito da seguire, sarà molto più semplice inserire questo nuovo tipo dato solo per i documenti che lo necessitano, lasciando gli altri inalterati.

Normalizzazione vs denormalizzazione

In un contesto di database relazionale, è buona norma effettuare un’operazione di normalizzazione dei dati, per evitare duplicazioni e avere tabelle separate per ogni entità correlata che possano essere unite tra loro per produrre una visione completa dei dati.

L’esempio sopra riportato descrive questo approccio. Ogni studente ha una relazione 1:N con l’entità “Voti”, la quale descrive il voto che lo studente ha conseguito per un dato corso di studi. Inoltre l’entità “Voti” ha un’altra relazione, sempre 1:N, con l’entità “Corso di studio” che descrive, appunto, il relativo corso di studio associato. L’entità “Voti” ha due chiavi esterne: una che riporta l’id dello studente e l’altra che riporta l’id del corso di studi. Se necessitiamo di visualizzare i voti di un singolo studente, dovremo fare delle query join per poter avere queste informazioni. Le operazioni di persistenza dei dati non sono immediate a meno che non si utilizzi un Object-Relational Mapping Framework (ORM) come Entity Framework.

In questo caso, invece, possiamo vedere come le informazioni siano tutte contenute all’interno di un documento. Non sarà necessario andare a reperire informazioni in altri documenti oppure diversificare il salvataggio in quanto il tutto è contenuto, appunto, dentro un unico documento.

Lo scenario descritto è compatibile con una gestione NoSql; tuttavia è importante sottolineare che non sempre un database non relazionale è una scelta migliore di un database relazionale.

Se il database ha molte relazioni e normalizzazioni, potrebbe avrebbe poco senso l’utilizzo di un NoSql. Pensate, ad esempio, ad un blog contenente degli articoli e, per ogni articolo, tanti commenti. Dato che non sappiamo, a priori, quanti potranno essere i commenti, utilizzare un database NoSql rischierebbe di generare confusione, in quanto tutti i commenti dovrebbero essere all’interno di una lista dentro il documento relativo all’articolo (nessuno comunque vieta di creare un documento che contenga l’articolo e tanti documenti che contengono i vari commenti).

Un’altra casistica da considerare è la duplicazione dei dati. Non è raro che in un database NoSql ci siano dati duplicati su in più documenti, in modo che tali documenti siano indipendenti da altri. Ovviamente, se i dati gestiti hanno una frequenza elevata di aggiornamento, potremmo pensare di aggiornare tutti i documenti oppure estrarre i documenti con più alta frequenza di aggiornamento e utilizzarli in modo condiviso con gli altri. Anche in questo caso, tutto dipende dallo sviluppatore e da come imposta la struttura dei dati. Dobbiamo ricordare, però, che i database NoSql sono adatti alla gestione di dati che sono quasi o del tutto consistenti.

E adesso, LiteDB

Dopo questo excursus, siamo pronti per vedere come utilizzare LiteDb all’interno di una nostra applicazione.

LiteDb è arrivato alla versione 5, che è quella che utilizzerò in questo articolo.

La prima cosa da fare è aggiungere una referenza Nuget del package LiteDB. A questo punto creiamo una classe che descriva l’entità Studente:

public class Student
{   
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public DateTime DateOfBirth { get; set; }
}

Successivamente, effettuiamo le operazioni di CRUD con LiteDb:

using(var db = new LiteDatabase(@"C:\Temp\Students.db"))
{
    var collection = db.GetCollection<Student>("student");
    var student = new Student
    {
        Name = "Pippo",
        Surname = "Franco",
        DateOfBirth = new DateTime(1940, 9, 2)
    };
    collection.Insert(student);
    student.Surname = "Rossi";
    collection.Update(student);
    collection.EnsureIndex(x => x.Surname);
    var results = collection.Query()
        .Where(x => x.Name == "pippo")
        .ToList();

}

Come potete vedere, l’utilizzo è veramente semplice.

Viene creata la collezione Studenti (oppure ci viene restituita se già esiste) da lì, la potremo utilizzare come una vera e propria lista, solo che ciò che inseriremo verrà salvato all’interno di un file chiamato, nel nostro caso, “Students.db”.

Dato che quello che abbiamo “tra le mani” è una collezione, possiamo utilizzare LINQ per effettuare operazioni di filtraggio, ordinamento etc.

Essendo un database NoSql, LiteDb effettua il salvataggio dei dati in quello che ho descritto prima come documento. All’interno del documento i dati sono persistiti usando il formato BSON, ovvero una rappresentazione binaria di JSON con tipizzazione dei dati. LiteDb utilizza un sottoinsieme dei tipi previsti dalla specifica BSON. [http://bsonspec.org/spec.html]

Per consultare e modificare i documenti tramite una semplice interfaccia vi consiglio LiteDB Studio che potete scaricare qui. [https://github.com/mbdavid/LiteDB.Studio]

Qui sopra il risultato di ciò che abbiamo creato appena qualche riga sopra.

Con questo, ho cercato di darvi una breve panoramica sul mondo NoSql e su uno dei database più utilizzati, spero di essere stato utile. Alla prossima!

Crediti per materiale grafico Designed by fullvector / Freepik

Leggi anche BAAS – GOOGLE FIREBASE