Blog (12)
Komentarze (42)
Recenzje (0)

RavenDB i C# - Czyli NoSQL w świecie .net

@mcywinskiRavenDB i C# - Czyli NoSQL w świecie .net22.08.2013 20:55

Obecnie jestem na stażu w pewnej firmie programistycznej w Warszawie i odbyłem już prawie dwumiesięczny kawał ciekawej praktyki. Jednym z zadań, które otrzymałem było zapoznanie się z możliwościami bazy danych NoSQL – RavenDB - którą być może (ale nie na pewno) wykorzystam w pracy z kolejnymi (i niekoniecznie firmowymi) projektami.

Zagadnienie RavenDB na tyle mnie zainteresowało, że postanowiłem napisać ten tekst, a ponadto piszę go też z powodu małej liczby polskich wpisów w Internecie traktujących na tak ciekawy temat. Najpierw chciałbym zrobić szybki rys teoretyczny – którego brakowało mi, gdy dopiero poznawałem RavenDB, a następnie spróbuję to poprzeć przykładami i przykładowym programem do pobrania na końcu wpisu. Mam nadzieję, że coś takiego pomoże innym zainteresowanym szybciej poznać podstawy działania tej ciekawej bazy danych. Wpis ten zatem można potraktować jako nieoficjalny "Quick start guide".

Z góry powiem, że dla programisty dostępne są dwa API: API http z którego można korzystać z poziomu dowolnego języka i wygodne api .net-owe na przykład dla programistów języka C#.

O co chodzi z NoSQL? – rys teoretyczny

Jak sama nazwa wskazuje, w bazach NoSQL rezygnujemy z licznych relacji, tabel oraz kluczy w bazie danych. Zamiast tego w RavenDB posługujemy się dokumentami zgromadzonymi w jednym miejscu na wzór jednej tabeli. Dokument jest to dokładna reprezentacja obiektu przekazanego z programu w naszej nierelacyjnej bazie danych w formacie JSON.

Jak zatem rozwiązujemy kwestię relacji i logicznego powiązania wielu różnych obiektów? Odpowiedzią na to pytanie są wszelkiego rodzaju kolekcje umieszczone jako propercje naszego obiektu.

Skoro mamy o czynienia ze zwykłymi dokumentami JSON, to możemy wszystkie hierarchicznie reprezentować. Np.: obiekt szkoła może mieć w sobie kolekcję nauczycieli i kolekcję uczniów. Baza danych za nas to spokojnie obsłuży - Przy próbie zapisu "łyknie" dowolny obiekt, który jest również dowolnego typu.

Rozwiązanie to jest bardzo skalowalne. Założeniem twórcy było to, aby serwer bazy danych miał możliwie jak najdłuższy uptime – wszystkie operacje możliwie powinny być możliwe łącznie z przebudową struktury bazy bez downtime’u naszej aplikacji. Warto wspomnieć, że wspierany jest również Sharding, czyli rozbicie danych pomiędzy wieloma serwerami, choć z punktu widzenia zewnętrznego jest to widziane jako jedna baza danych.

Dodatkowo jednym z założeń twórcy było podejście, że lepiej aby klient otrzymał jakiekolwiek dane i szybciej, aniżeli dłużej i aktualne. Dlatego pomimo skalowalności to na programiście spoczywa obowiązek zadbania o spójność danych i w niektórych projektach może postawić pod znakiem zapytania użycie RavenDB.

Jak to działa w praktyce? Prosto! W RavenDB możemy przetrzymywać obiekty różnego typu (zwane dokumentami) i nie „zmieszają” się. Nie definiujemy w bazie żadnych kolumn, ponieważ generują się one same na podstawie wstawianego do niej obiektu. Działa to również w drugą stronę: Wypełnione są tylko pola tej klasy, którą „wybieramy” z bazy danych. Pozostaje jeszcze kwestia manipulacji danymi. Skoro rozwiązanie jest NoSQL-owe, to i nie ma starej dobrej składni SQLa. Na pomoc przychodzi programistom C# sprawdzone, dobre i - przede wszystkim - dobrze znane LINQ i Lucene Syntax, które dla większości osób może okazać się nowością.

Twórcy RavenDB zintegrowali z silnikiem bazy danych mechanizm odpytywania Lucene - który niezależnie od bazy danych może zostać zaimplementowany w dowolnych .netowych projektach.

Jak to wygląda w praktyce? Przekonajmy się!

Rys praktyczny - podstawy RavenDB

Wszystko potrzebne do pracy z RavenDB jest dostępne do pobrania pod adresem http://ravendb.net/

Rozpakowane archiwum zawiera plik wsadowy Start.cmd, który startuje serwer developerski.

Widok logu serwera developerskiego RavenDB
Widok logu serwera developerskiego RavenDB

Wywołane okno konsoli pozwala na dodatkowy debugging naszej aplikacji po stronie bazy danych, ponieważ wyświetla wszstkie przychodzące do serwera requesty i liczbę zwróconych wyników, a także operacje które niekoniecznie zwracają dokumenty z bazy danych. Dodatkowo wraz z wywołaniem tego okna konsoli, w przeglądarce automatycznie zostaje wywołany webowy interfejs do zarządzania bazami danych.

Zarządznanie bazą danych z poziomu przeglądarki jest wygodne. Zostało zrealizowane przez aplikację Silverlight.
Zarządznanie bazą danych z poziomu przeglądarki jest wygodne. Zostało zrealizowane przez aplikację Silverlight.

Skoro działa już bazodanowe serce naszych przyszłych aplikacji, to spróbujmy połączyć się z poziomu C# z Ravenem i dodać tam jakieś dane. W projekcie C# wystarczy za pomocą NuGeta pobrać API do łączenia się z RavenDB lub załączyć pliki dll dołączone do paczki pobranej ze strony RavenDB.

Nie musimy się nawet trudzić szukaniem DLL. Aktualne API dostępne jest w NuGecie :)
Nie musimy się nawet trudzić szukaniem DLL. Aktualne API dostępne jest w NuGecie :)

Potem już tylko podajemy odpowiednie referencje w kodzie:

[code=C#]using Raven.Client; using Raven.Client.Document;[/code]

Powyższe dwie linijki importują nam dwie przestrzenie nazw. Pierwsza służy ściśle do utworzenia obiektów potrzebnych do połączenia z bazą danych. Druga przestrzeń nazw udostępnia nam zestaw klas przydatnych w manipulacji danymi - dokumentami. Spróbujmy więc użyć tych klas do zapisania czegoś w bazie danych. Naturalnie, w pliku app.config dodaję connection string dla RavenDB:

[code=XML]<add name="Server" connectionString="Url = http://localhost:8080;Database=test"/>[/code]

Kolejnym krokiem prowadzącym nas do połączenia się z bazą jest stworzenie obiektu klasy DocumentStore i wywołanie metody Initialize:

[code=C#]IDocumentStore store = new DocumentStore { ConnectionStringName = "Server" }; store.Initialize();[/code]

Użyłem do tego celu interfejsu IDocumentStore, ponieważ może on być również obsłużony przez shardowane rozwiązane - w którym kilka serwerów jestwidziane jako jeden DocumentStore.

Do wszelkich operacji na bazie danych otwieramy zaś sesję. Na końcu sesji zapisywane są dane w bazie metodą SaveChanges. Ważną rzeczą jest aby pamiętać, że sami twórcy RavenDB nie zalecają używania więcej niż jednej sesji/program. Wymusza to nas odpowiednie okodowania komunikacji z bazą danych, ale ma to też zazwczaj dobre odbicie na jakości naszego kodu ;)

[code=C#]using (IDocumentSession session = store.OpenSession()) { //Tutaj się dzieje magia, a później zostaje ona zapisana :) session.SaveChanges(); }[/code]

Skoro mamy wszystko, to zdefiniujmy obiekt do zapisu w bazie:

[code=C#]class Person { public string name; public int age; public string nickname; }[/code]

I wreszcie zapis przykładowych danych przy użyciu naszej wcześniej otwartej sesji:

[code=C#]using (IDocumentSession session = store.OpenSession()) { Person jan = new Person { age = 20, name = "Jan Kowalski", nickname = "Janek16" };

Person pawel = new Person { age = 25, name = "Paweł Nowak", nickname = "pablo2" };

session.Store(jan); session.Store(pawel); session.SaveChanges(); } }[/code]

Powyższy przykład świetnie pokazuje jak łatwo można zapisywać dane przy pomocy API RavenDB. I uwierzcie mi, łyknie każdy obiekt - nawet z mnóstwem kolekcji zagnieżdżonych na różnych poziomach :)

Warto równocześnie spojrzeć co na to wszystko powiedział log naszego serwera bazy:

Tak w logu wygląda poprawnie zapisanie dwóch obiektów
Tak w logu wygląda poprawnie zapisanie dwóch obiektów

Skoro tak prosto poszło z zapisem, spróbujmy analogicznie odczytu. Pierwszą możliwością jest użycie Linq:

[code=C#]var results = from company in session.Query<Company>() where company.Name == "Hibernating Rhinos" select company;[/code]

Skoro Linq jest raczej dobrze znane (i lubiane), ja przedstawię za to zastosowania mechanizmu Lucene w RavenDB do wybrania danych.

[code=C#]using (IDocumentSession session = store.OpenSession()) { var results = session.Advanced .LuceneQuery<Person>() .Where("name:*wa*").ToList();

foreach (Person p in results) { Console.WriteLine(p.name); } }[/code]

Posługując się składnią podaną w linku na początku wpisu wybrałem wszystkie elementy, które w propercji Name zawierają w sobie podciąg "wa". Zatem zobaczmy wyniki programu i log:

Dane zostały poprawnie wybrane, całość odzwierciedla również log
Dane zostały poprawnie wybrane, całość odzwierciedla również log

Podsumowanie

To co przedstawiłem w tym wpisie to tylko wierzchołek góry lodowej. RavenDB pozwala na znaczenie więcej, w tym wspomniany już sharding, wyszukiwanie pełnotekstowe oraz bardzo zaawansowane odpytania.

Mam nadzieję, że mój wpis na temat nierelacyjnej bazy danych dla .net okaże się dla niektórych osób pomocny.

Jeżeli gdzieś popełniłem błąd merytoryczny - przepraszam :) Chętnie go poprawię.

[Link do przykładowego projektu ]

Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.