Accueil > .Net, ASP.Net, C#, MongoDB, NoSQL > [C# MongoDB] Overview

[C# MongoDB] Overview

MongoDBBon, ça fait un moment que j’écris des brouillon sur WordPress, dans Gmail et des .doc…
Mais finalement, je publie plus rien…
Donc, je prends mon courage à deux mains (mais bon, certes, elles restent sur le clavier) et j’y vais ! (nettoyage/publication…)

Aujourd’hui, on va parler de MongoDB, une base de données NoSQL qu’elle et bien (si, si, j’vous jure).
(Attention, GROS pavé)


 

Introduction.

 
MongoDB, c’est quoi ? Une base de données NoSQL.

C’est quoi du NoSQL ?
Ce sont des bases de données non relationnelles. En somme, aucun schéma (SchemaLess), mais plutôt orientée entité. Grosso modo, cela veut dire qu’on oublie les tables, les primary key, foreign key (bon, y en a qui les oublies aussi dans des SGBDR…) etc.
On oublie aussi les ORM qui peuvent être une plaie en début de développement (quand le modèle change en fonction des besoins à géométrie variable et de se retrouver avec des colonnes fourre-tout ayant de doux noms comme « attribute_1 », « attribute_2 » et compagnie).

Le développeur aura uniquement à créer ses objets métiers et à demander à la base de les stocker. Point.
Par contre TOUT l’objet est stocké, donc penser un minimum à la modélisation parait une bonne idée ! (mais bon, cela reste quand même un pré-requis avant de coder, non ?)
C’est donc une base orientée Documents (un document = un objet du code ; sous un format JSON-like : BSON pour Binary JSON).

Quels sont les autres avantages ?
Déjà, les bases NoSQL permettent de gérer beaucoup de données.
Par exemple, des structures, somme toute modestes, comme Google, Amazon, Facebook et d’autres utilisent des base NoSQL.
Ce n’est pas comme si elles devaient gérer beaucoup d’infos, non ?

Elles sont également très simples à manipuler, pas besoin d’être un pro-SQL pour récupérer des objets en base (voir même inutile de savoir faire du SQL).

Coté code, on retrouvera une grande flexibilité : on modifie l’objet du code selon les besoins et pis c’est tout.

Après, autre avantage non négligeable : le déploiement. Dans la todo list, on trouve…rien.
Autrement dit, il est aussi bien possible d’avoir une grosse base de données pour l’application qu’avoir une base de données par utilisateur.

Enfin, la majeure partie (sinon toutes)  les bases de données NoSQL sont…open source. Donc on oublie le prix d’une licence qui coûte les deux bras (et parfois un œil  et la peau du…enfin, vous voyez).

Et donc, pourquoi MongoDB ?
Euh…c’est le nom que je connaissais le plus dans le domaine 🙂
C’est tout !

J’aurais donc pu regarder (et je le ferais peut-être) d’autres bases, mais j’ai choisis de commencer par là, sans raison philosophique particulière.

 

Installation de MongoDB.

 

C’est d’une simplicité enfantine.
A comparer avec l’installation d’une base Oracle, par exemple ! (ou pour troller : une base DB2 !) ;-).

Déjà, on se rend sur le site officiel de MongoDB, rayon téléchargements.

On prend la version qui convient pour Windows (bah oui, développeur .Net, donc Windows !).
Une fois l’archive téléchargée, on l’extrait.
Voilà…c’est tout pour ce qui est de la base à proprement parlé.

Note :
Ici, je n’installe pas le serveur de MongoDB sous forme de Service Windows.
Pour le faire, il faut utiliser la commande :

mongod.exe --install --logpath "<chemin>\server.log"

Après, il faut installer les drivers.
On se rend donc toujours sur le site de MongoDB.
Ou directement sur github.

J’ai pris le MSI comme un grand fainéant.
Une fois téléchargé, j’ai installé le MSI avec la démarche bien connue du « Suivant, Suivant, Suivant, Terminé ».
Ca y est. On a finit l’installation de drivers ! 🙂

Oulà, ça prend au moins…moins de temps que pour boire un café !

 

Démarrage du serveur.

 

(Partie non valable si le Service Windows est installé)
J’ai pris la version Windows 32 bits, donc je vais dans \mongodb-win32-i386-2.0.5\bin.
Je copie le chemin, je démarre une invite de commande, vais dans le répertoire qui va bien et…tape la commande :

mongod.exe –dbpath "<chemin ou sera stocké la base>"

Je spécifie le chemin car par défaut, MongoDB va localiser la base dans :\data\db, mais comme j’ai mis la base sous contrôle de code source (oui, c’est violent, mais je peux, c’est pratique, alors je fais), ce n’est pas là qu’elle sera.

Du coup, j’obtiens plus ou moins l’affichage suivant :
MongoDB - Serveur

Bien sûr, en utilisant le service Windows, c’est pas la peine de démarrer le serveur ainsi.
Mais en phase de développements (et aussi pour comprendre comment le driver gère les choses), je trouve assez utile d’avoir la console sous les yeux.
Bon, après, j’avoue, le troisième jour d’utilisation, j’ai lancé le site en oubliant de lancer le serveur… XD

 

Dans le code .Net.

 

Dans un premier temps, on va ajouter les références qui vont bien.
Les assemblys se trouvent le GAC après installation du driver, il faut à minima celles-ci :

  • MongoDB.Bson
  • MongoDB.Driver

Les using suivants vont être utilisés :

using MongoDB.Driver;
using MongoDB.Driver.Builders;

Dans un premier temps, avant de devoir requêter la base comme des brutes, il faut faire un minimum de paramétrage :

String connectionString = "mongodb://localhost/?safe=true";
String databaseName = "DemoMongoDb";

MongoServer server = MongoServer.Create(connectionString);
MongoDatabase database = server.GetDatabase(databaseName);

J’avais bien dit minimum, hein ? 🙂

Pour plus de détail sur les chaînes de connexion, il faut se référer à la documentation de MongoDB..

On a donc créé le serveur ainsi que la base de données.
Il n’est vraiment pas utile de conserver l’objet « server ».
Par contre, l’objet « database » est plus pertinent à conserver à partir du moment où l’on va créer plusieurs collections.

Qu’est ce que c’est, une collection ?
Basiquement, c’est le lieu de stockage d’un type spécifique d’entité. C’est cette collection que l’on va requêter. Il en faudra donc une par type d’objet à stocker.
C’est comme cela qu’on la récupère :

MongoCollection<UserInfo> UserCollection = database.GetCollection<UserInfo>("UserCollection");

Il n’est pas obligatoire de typer la collection. Cependant, il faudra alors utiliser les méthodes génériques pour récupérer les données (FindOneAs au lieu de FindOne, FindAllAs au lieu de FindAll…, comme on le voit ensuite).

Pour l’objet (ici, UserInfo), il faut à minima qu’il possède une propriété Id, de type MongoDB.Bson.ObjectId.
En effet, MongoDB va se charger de gérer les identifiants uniques, comme un grand.
C’est à l’insertion dans la base que l’Id va être alimenté, avant cela, il possède une valeur par défaut non significative.
Il aura cette tête là :
MongoDB - ObjectId
Ceci dit, il est très bien possible d’utiliser un autre Id que celui généré par MongoDB, il suffit d’utiliser l’attribut : MongoDB.Bson.Serialization.Attributes.BsonId sur la propriété qui servira d’identifiant (par exemple un Guid).

De plus, il est possible d’ignorer la sérialisation de certaines propriétés, simplement en utilisant l’attribut : MongoDB.Bson.Serialization.Attributes.BsonIgnore.

La documentation MongoDB au sujet de la sérialisationest bien faite.

Et justement, comme on fait un CRUD ?
Très simplement:

public void Insert(UserInfo obj)
{
    SafeModeResult result = UserCollection.Insert(obj);
    // traitement d'erreur et compagnie
    //result.Ok = true si tout s'est bien passé
}
public IList<UserInfo> GetAll()
{
    IList<UserInfo> users = new List<UserInfo>();
    foreach (UserInfo item in UserCollection.FindAll())
        users.Add(item);
    return users;
}

A noter que les méthodes FindAll ou FindAllAs renvoient des MongoCursor.
Le curseur n’est alimenté que lorsque l’on itère dessus.
De plus, il est possible de limiter le nombre de lignes retournées grâce aux propriétés BatchSize et Limit (ou les méthods SetBatchSize et SetLimit).

public UserInfo Select(ObjectId id)
{
    return UserCollection.FindOne(Query.EQ("_id", id));
}

On remarque bien le « _id », alors que dans ma class, c’est la propriété « Id », c’est normal, il faut le considérer comme un alias.
Mis à part ce champ particulier, on pourra avoir accès à tous les champs avec le nom de la propriété (exemple dans le Update).

public void Update(UserInfo obj)
{
    IMongoQuery query = Query.EQ("_id", id);
    IMongoUpdate update =
        MongoDB.Driver.Builders.Update
            .Set("AvatarUrl", obj.AvatarUrl)
            .Set("BirthDate", obj.BirthDate)
            .Set("FirstName", obj.FirstName)
            .Set("LastName", obj.LastName)
            .Set("MailAdress", obj.MailAdress)
            .Set("Password", obj.Password);
    SafeModeResult result = UserCollection.Update(query, update);
    // traitement d'erreur et compagnie
    //result.Ok = true si tout s'est bien passé
}

Chaque propriété modifiable doit être spécifiée, il n’est pas possible de passer l’objet en lui-même (dommage, mais bon, il est facile de s’en remettre).

public void Delete(UserInfo obj)
{
    SafeModeResult result = UserCollection.Remove(Query.EQ(("_id", obj.id));
    // traitement d'erreur et compagnie
    //result.Ok = true si tout s'est bien passé
}

Note :
A aucun moment il n’est utile de gérer les connexions via des méthodes Connect(), Open(), Disconnect(), Close() ou autres.
C’est le driver qui s’occupe de tout ! (il utilise un pool de connexions)

 

Conclusion.

 

Comme on a pu le voir dans ce billet, l’utilisation de MongoDB est quand même très simple.
Si on combine la simplicité d’utilisation à sa puissance, cela en fait une base de données vraiment très bonne, une réelle alternative aux SGBD classique qui ont u coût non négligeable (licence, serveurs, etc.).

Un très gros avantage, c’est que l’on peut entièrement se concentrer sur le code et cela force également à avoir une logique métier dans le code (pas de procédures stockées = aucune intelligence à la fois dans le code et les procs) et uniquement dans le code.

De plus, je trouve les performances (sur ma machine, s’entend) meilleures que sur une base Oracle ou Sybase (via réseau) ou SQLServer (localhost). Mais cela reste au feeling, je n’ai pas pris trop la peine de faire de mesure.

 

Pour aller plus loin.

 

Il y a un utilitaire pour tester MongoDB en ligne.
On peut aussi trouver des infos sympas sur mongly, un PDF/epub présentant MongoDB est disponible à partir de ce billet.

Quant à des tests de performances, on peut en trouver au moins un ici (un peu vieux, mais ça peu donner une idée).

Il est possible de retrouver un nombre important de bases NoSQL sur…NoSQL Database

Il est aussi possible de requêter les bases existantes en lignes de commande grâce à l’utilitaire « mongo.exe », dans une invite de commandes.
Cet interpréteur est en fait un shell javascript connecté à la base.

Enfin, pour le MSDN Magazine de Mai 2010, Ted Neward avait écrit un billet : Adopter NoSQL avec MongoDB.
La version de l’époque était la 1.2.4 (2.0.5 depuis le 09/05/2012). Mais une très grosse moitié du billet reste valable (avant la partie « Ecriture du code », surtout, je trouve).

Catégories :.Net, ASP.Net, C#, MongoDB, NoSQL

Laisser un commentaire