Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

API per C#

Utilizzare il driver ufficiale per C# al fine di effettuare tutte le principali operazioni CRUD per interagire con MongoDB.
Utilizzare il driver ufficiale per C# al fine di effettuare tutte le principali operazioni CRUD per interagire con MongoDB.
Link copiato negli appunti

Tra i principali linguaggi di programmazione utilizzati per la programmazione lato server, uno è certamente C#, che unitamente al framework .NET è spesso utilizzato nelle soluzioni basate su software Microsoft.

In questa lezione vedremo come interfacciarsi con un database MongoDB utilizzando il driver ufficiale per il linguaggio C#. Partiremo dall'installazione, e vedremo tutte le principali operazioni supportate.

Installazione

La prima cosa da fare è ottenere il driver per C#. Possiamo fare riferimento al sito ufficiale, dal quale possiamo scaricare il pacchetto da installare (seguendo le istruzioni riportate). Sebbene questa opzione sia comunque semplice, la soluzione migliore (soprattutto in considerazione del fatto che spesso si lavora su Visual Studio) è quella di affidarsi a NuGet, il package manager incluso già in tutte le versioni recenti della celebre IDE di Microsoft.

Facendo riferimento a Visual Studio 2013 (sebbene il procedimento sia pressocché analogo anche per le versioni successive), una volta creato il nostro progetto, è sufficiente selezionare la voce di menu Progetto, selezionando poi Gestisci pacchetti NuGet...

Nella finestra che si aprirà, inseriamo nel campo di ricerca in alto a destra la stringa "MongoDB", e premiamo il tasto Invio. Tra le opzioni visualizzate, troveremo MongoDB.Driver: selezioniamo la voce e premiamo sul pulsante Installa visualizzato a destra.

Figura 1. Installazione del driver di MongoDB per C# (click per ingrandire)

Installazione del driver di MongoDB per C#

Completata l'installazione, assicuriamoci di aggiungere al nostro progetto i riferimenti alle .dll MongoDB.Bson.dll, MongoDB.Driver.dll e MongoDB.Driver.Core.dll (tutte incluse nel pacchetto appena scaricato mediante NuGet).

A questo punto, non resta che iniziare a programmare.

Connessione al database

Per interagire con il database, dobbiamo innanzitutto specificare quali riferimenti utilizzare, mediante le opportune clausole import:

using MongoDB.Bson;
using MongoDB.Driver;

Fatto ciò, sfruttiamo ora le funzionalità messe a disposizione dal driver C# per connetterci al database. Sono sufficienti le righe seguenti:

protected static IMongoClient client;
protected static IMongoDatabase database;
client = new MongoClient();
database = client.GetDatabase("test");

A questo punto, utilizzeremo l'oggetto database per eseguire la maggior parte delle operazioni CRUD.

Inserimento di documenti nel DB

Per inserire un documenti, dobbiamo innanzitutto generarlo. La creazione di un documento avviene mediante la classe BsonDocument:

var document = new BsonDocument
{
{ "indirizzo", new BsonDocument
{
{ "via", "Viale Sarca, 336" },
{ "cap", "20126" },
{ "edificio", "16" }
}
},
{ "citta", "Milano" },
{ "stato", "Italia" },
{ "note", new BsonArray
{
new BsonDocument
{
{ "data", new DateTime(2017, 10, 2, 0, 0, 0, DateTimeKind.Utc) },
{ "contenuto", "Test 1" }
},
new BsonDocument
{
{ "data", new DateTime(2014, 2, 7, 0, 0, 0, DateTimeKind.Utc) },
{ "contenuto", "Test 2" }
}
}
},
{ "nome", "HTML.it" }
};

Definito il documento, l'inserimento avviene mediante il metodo InsertOneAsync della classe MongoCollection. Ovviamente dovremo specificare in quale collection inserire il documento. Procederemo quindi così:

var collection = database.GetCollection<BsonDocument>("lamiacollection");
await collection.InsertOneAsync(document);

Si noti che il metodo InsertOneAsync non restituisce alcun valore di ritorno. Inoltre, se l'oggetto di tipo BsonDocument, passato come argomento a InsertOneAsync, non contiene un campo _id, quest'ultimo verrà generato automaticamente all'atto dell'inserimento del documento nella collection.

Selezione: eseguire una query

Per selezionare (e quindi leggere) i dati dal database, il driver C# mette a disposizione 2 metodi: Find e FindAsync. Entrambi questi metodi ritornano un documento o un insieme di documenti, in base al criterio di filtraggio specificato.

Il metodo FindAsync restituisce i risultati della query in un oggetto IAsyncCursor, che è iterabile. Il metodo Find, invece, produce un oggetto IFindFluent, che può essere convertito in una lista di documenti tramite il metodo ToListAsync.

Per ottimizzare l'uso della memoria, è consigliabile utilizzare i metodi asincroni, e per questo motivo opteremo per tale soluzione negli esempi che seguono.

Vediamo subito come richiedere la lista di tutti i documenti di una collection:

var collection = database.GetCollection<BsonDocument>("lamiacollection");
var filtro = new BsonDocument();
var count = 0;
using (var cursor = await collection.FindAsync(filtro))
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
foreach (var document in batch)
{
// iterare su batch permette di leggere tutti i documenti (document)
count++;
}
}
}

In questo caso, il filtro rappresenta un oggetto BSON vuoto, che deve comunque essere passato al metodo FindAsync. I risultati sono poi utilizzati in un ciclo while, sfruttando il metodo MoveNextAsync() e leggendo la proprietà Current dell'oggetto cursor (di tipo IAsyncCursor).

Se vogliamo specificare opzioni di filtraggio più specifiche, è consigliabile sfruttare la classe Builders, pensato proprio per questa esigenza. Supponiamo, per esempio, di volere selezionare tutti i documenti con l'attributo citta uguale a Milano:

var filtro = Builders<BsonDocument>.Filter.Eq("citta", "Milano");

Il metodo Eq è quindi utilizzato per specificare filtri basati su condizioni di equivalenza. Alternativamente, possiamo utilizzare i metodi Lt e Gt (rispettivamente, less than - minore di - e greater than - maggiore di) per realizzare disuguaglianze.

Facendo riferimento alla struttura del documento vista in precedenza, possiamo anche specificare tali condizioni su parti di documento annidate (sfruttando la cosiddetta dot notation). Ad esempio, il codice seguente mostra come selezionare i documenti il cui campo indirizzo ha un sottocampo cap pari a 91021:

var filtro = Builders<BsonDocument>.Filter.Eq("indirizzo.cap", "91021");

È altresì possibile combinare più filtri tramite gli operatore & (AND logico) e | (OR logico), come mostrato nell'esempio seguente:

var builder = Builders<BsonDocument>.Filter;
var filtro = builder.Filter.Eq("indirizzo.cap", "91021") & builder.Filter.Eq("citta", "Milano");

Infine, per ordinare i risultati rispetto ad un certo campo, utilizziamo i metodi Sort.Ascending e Sort.Descending:

var sort = Builders<BsonDocument>.Sort.Ascending("citta").Descending("indirizzo.cap");

L'oggetto sort così costruito sarà poi utilizzato, insieme al filtro, per generare l'insieme dei risultati. Ad esempio:

var result = await collection.Find(filtro).Sort(sort).ToListAsync();

Maggiori dettagli possono essere reperiti facendo riferimento al tutorial ufficiale.

Modificare un documento

Le operazioni di aggiornamento sono realizzate mediante i metodi UpdateOneAsync (per aggiornare un solo documento) e UpdateManyAsync (per aggiornare più documenti). Anche in questo caso, per costruire le query di aggiornamento, si utilizzano i Builders.

Vediamo un esempio in cui aggiorniamo un campo di un documento:

var collection = database.GetCollection<BsonDocument>("lamiacollection");
var filtro = Builders<BsonDocument>.Filter.Eq("citta", "Milano");
var update = Builders<BsonDocument>.Update
.Set("stato", "San Marino")
.CurrentDate("lastModified");
var result = await collection.UpdateOneAsync(filtro, update);

Anche in questo caso effettuiamo una selezione mediante l'oggetto filtro, mentre Update.Set permette di specificare il campo da aggiornare (unitamente al nuovo valore). Se avessimo voluto modificare un campo all'interno della struttura del documento, avremmo dovuto utilizzare la stessa dot notation vista negli esempi precedenti. Inoltre, poiché utilizziamo il metodo UpdateOneAsync per effettuare l'aggiornamento, soltanto il primo dei valori corrispondenti al criterio specificato dal filtro sarà effettivamente aggiornato. L'unica modifica richiesta per aggiornare tutti i documenti selezionati tramite il filtro specificato, era l'uso del metodo UpdateManyAsync:

var result = await collection.UpdateManyAsync(filtro, update);

Esiste anche la possibilità di sostituire un documento esistente, specificando il solo campo _id nel filtro, ed il nuovo documento come secondo argomento del metodo ReplaceOneAsync:

var result = await collection.ReplaceOneAsync(filtro, nuovo_documento);

Anche per le operazioni di aggiornamento, tutti i dettagli possono essere reperiti sul tutorial ufficiale.

Eliminazione dei documenti

L'ultima tipologia di operazioni che dobbiamo analizzare riguarda la possibilità di eliminare dati dal database. I metodi da utilizzare sono DeleteOneAsync e DeleteManyAsync. Vediamo subito un esempio:

var collection = database.GetCollection<BsonDocument>("lamiacollection");
var filtro = Builders<BsonDocument>.Filter.Eq("citta", "Milano");
var result = await collection.DeleteManyAsync(filtro);

Come si vede, il funzionamento è analogo a quelli precedenti: dobbiamo specificare un filtro (sempre mediante Builders), e passarlo come argomento ai metodi preposti alla rimozione.

Un caso particolare è quello in cui si vogliano rimuovere tutti i documenti di un database (operazione rischiosa, ma talvolta utile). In questo caso è sufficiente utilizzare, come filtro, un documento BSON vuoto:

var result = await collection.DeleteManyAsync(new BsonDocument());

Se vogliamo rimuovere un'intera collection, ricorriamo invece al metodo DropCollectionAsync:

await database.DropCollectionAsync("lamiacollection");

Ulteriori informazioni sulle operazioni di eliminazione dei dati sono disponibili nell'apposito tutorial ufficiale.

Ti consigliamo anche