No Sql No Problem, czyli MongoDB, NoRM i .NET .
Pierwsze relacyjne bazy danych powstały w latach ‘70 ubiegłego wieku, na długo przedtem nim języki programowania zorientowane obiektowo stały się popularne. Obecnie są standardem jeśli chodzi o mechanizm persystencji w programowaniu obiektowym.
Jednak o tym, że translacja obiektowego modelu na relacyjny jest bardzo często procesem karkołomnym, nieprzyjemnym i błędogennym wielu z nas z pewnością doświadczyło na własnej skórze. Jest tak ponieważ model obiektowy z natury hierarchiczny nijak się ma do sztywnej struktury relacyjnej bazy danych (impedance mismatch). Nie zmienia to jednak faktu, że współpraca z RDBMS’ami stanowi i pewnie jeszcze długo stanowić będzie integralną część pracy większości programistów.
Możemy i powinniśmy korzystać z wszelakiej maści ORM’ów, pozwalających nam mapować obiektowy model na relacyjny, tworzących niejako “wirtualną obiektową bazę danych” bedącą pewnym rodzajem abstrakcji “nałożonym” na bazę relacyjną. Jednakże i one nie są złotym lekarstwem, często stwarzają problemy wydajnościowe ( select n+1, rozległe joiny itp.) i wymagają dużej wiedzy od programisty (lazy loading, zarządzanie sesją itp.).
A czy nie chciał byś po prostu nie myśleć o bazie danych? Nie musieć przejmować się ciągłymi migracjami, problemami z wydajnością, normalizacją? Echhhh, gdyby tylko się tak dało, ale dane trzeba gdzieś przechowywać. Potrzebujemy jednak czegoś prostego w użyciu, a jednocześnie wydajnego i stabilnego.
Poniżej przedstawiony jest bardzo prosty przykład użycia MongoDB wraz z NoRM w aplikacji .NET. (jeśli nie wiesz co oznaczają te tajemnicze nazwy, nic się nie martw-wyjaśnię wszystko za chwilę)
Zdefiniujmy dwie klasy Post i Comment :
public class Post
{
public string AuthorName { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public IList<Tag> Tags{ get; set; }
public IList<Comment> Comments { get; set; }
}
public class Comment
{
public string Body { get; set; }
public string AuthorName { get; set; }
}
Tworzymy nowego posta wraz z dwoma komentarzami:
var post=new Post()
{
AuthorName="Codefather"
Title= "No Sql No problem",
Body = "Some text",
Tags = new List<string> {".Net", "c#", "nosql"}
};
var rdbmsDefenderComment = new Comment()
{
AuthorName = "Rdbms defender",
Body = "nosql sucks"
};
var noSqlDefnederComment = new Comment()
{
AuthorName = "NoSql defender",
Body = "nosql is great"
};
post.Comments=new List<Comment>
{
rdbmsDefenderComment,
noSqlDefnederComment
};
Teraz trzeba naszego świeżo stworzonego posta trzeba jakoś zapisać. Nic prostszego:
using (var mongo = Mongo.Create("mongodb://localhost/CodefatherDB"))
{
mongo.GetCollection<Post>().Insert(post);
}
Powyższy kod robi trzy rzeczy:
- tworzy bazę danych o nazwie CodefatherDB
- tworzy kolekcję Post’ów (kolekcja to odpowiednik tabeli w MongoDB)
- dodaje stworzonego przez nas Post’a do tej kolekcji.
Teraz czas na “wyciągnięcie” naszego posta z bazy danych:
var retrievedPosts = mongo.GetCollection<Post>().AsQueryable()
.Where(p => p.Title == "No Sql no problem")
.SingleOrDefault();
Powyższy przykład jest bardzo prosty i zrozumiały (mam nadzieję), obrazuje jednocześnie jak łatwe i przyjemne jest korzystanie MongoDB.
Ale czym MongoDB właściwie jest ?
MongoDB to opensource’owa skalowalna (auto-sharding), wydajna (nawet bardzo wydajna), dokumentowa baza danych napisana w C++. Mimo swojego młodego wieku (tworzona jest od 2007 roku) zyskała sobie uznanie wielu ważnych graczy internetowego rynku tj: New York Times, SourceForge, FourSquere Github i co ciekawe wielki zderzacz hadronów w CERN pod Genewą (a raczej jego oprogramowanie-więcej informacji).
MongoDB przechowuje dane (dokumenty) w kolekcjach. Dokumenty to tak naprawdę obiekty JSON (a właściwie BSON), więc można w nich przechowywać bardziej skomplikowane dane (w porówaniu do tabel w RDBMS’ach), tj. inne obiekty (tzw. embedded documents), tablice czy słowniki. Modelowanie danych staje się dzięki temu bardziej naturalnym procesem, dając nam dużą swobodę.
Tak wygląda wcześniej zapisany nasz post w formacie JSON (w relacyjnej bazie danych były by to zapewne 3 tabele: posty, komentarze i tagi ):
{ Title : “No Sql no problem”, AuthorName: “CodeFather”, Body: “Some text”,
comments : [{ AuthorName: ““Rdbms defender”, Body: “nosql sucks” },
{ AuthorName : “NoSql defender”, Body: “nosql is great” } ],
tags:[{“.Net”, “c#”, “nosql”}]
}
MongoDB oferuje również dynamiczne tworzenie baz danych i kolekcji dokumentów,a brak schematu bazy, oznacza koniec problemów z migracjami.
Poniższy diagram doskonale obrazuje, gdzie plasuje się MongoDB na tle innych rozwiązań bazodanowych.

Instalacja MongoDB: czyli szybko sprawnie i bezproblemowo .
1. Pobieramy najnowszą wersję bazy stąd (uwaga: dla systemów 32bit maksymalny rozmiar bazy wynosi 2GB)
2. Rozpakowujemy do dowolnego katalogu na dysku.
3. W katalogu bin znajduje się mongod.exe , który poprostu odpalamy i w tym momencie nasz serwer bazodanowy już działa ! . Jeśli chcemy, MongoDB można bezproblemowo zainstalować jako serwis.
4. Domyślnie pliki z danymi MongoDB przechowuje w c:\data\db, więc jeśli nie mamy takiego katalogu to musimy go utworzyć lub przy uruchamianiu mongod.exe podać inną ścieżkę (––dbpath [path].)W tym momencie możemy odpalić shella (mongo.exe) i tworzyć z jego poziomu bazy,kolekcje, dokumenty, pisać zapytania itp. Nie jest to jednak zbyt wygodne, nie mówiąc już o współpracy z innymi językami.
Projekt NoRM (No Object-Relational Mapping)
NoRM jest biblioteką, pozwalającą na współpracę z MongoDB z poziomu .NET’a.
Główne jej cechy to :
- silnie typowanie,
- wsparcie dla Linq
- Automatyczna serializacja/deserializacja do formatu BSON
- łatwość użytkowania
- szybkość
Dzięki NoRM i MongoDB, nie ma potrzeby mapowania modelu obiektowego na inny, ponieważ struktura dokumentowa MongoDB jest bardzo zbliżona do struktury obiektowej. W skrócie: Obiekt ~ Dokument.

Dla mnie najważniejszą zaletą MongoDB i NoRM jest łatwość użycia- to poprostu działa! I to szybkoooooooo !!! Raz spróbujesz i już zawsze będziesz patrzeć na SQL’a z obrzydzeniem :)
Niestety mongoDB nie jest lekarstwem na wszystko. Nie wspiera transakcji w obrębie kilku dokumentów jednocześnie. Jeśli więc planujesz stworzyć np. system bankowy MongoDB może nie być najlepszym wyborem. Zachęcam do zapoznania się z Use Cases dla tej bazy.
Tyle tytułem wstępu. W przyszłości postaram zagłębić się w szczegóły i pokazać bardziej zaawansowane przykłady w oparciu o NoRM :)

