22/01/2012

RavenDB (cz. 2) - podstawowe operacje na dokumentach

Home

Wstęp

W drugim poście poświęconym Raven DB opiszę jak wykonywać podstawowe operacje (zapisz/usuń/zmień) na dokumentach. Ale czym jest dokument? Nie wiem jaka jest formalna definicja ale ja na dokumenty patrzę po prostu jak na obiekty zapisane (zserializowane) w formacie JSON. Poniżej przykład takiego dokumentu z mojego pet project, który odpowiada obiektowi klasy reprezentującej wyrażenie i jego tłumaczenia.
{
  "Category": "Geografia",
  "Expression": "wioska",
  "Translations": [
    {
      "Language": "Language1",
      "Translation": "Dorf",
      "GoodAnswers": 0,
      "BadAnswers": 1,
      "WasLastAnswerGood": false
    },
    {
      "Language": "Language2",
      "Translation": "village",
      "GoodAnswers": 1,
      "BadAnswers": 0,
      "WasLastAnswerGood": true
    }
  ]
}
Klasa, której obiekty chcemy wrzucić do Raven DB może być zwykłym POCO z dokładnością do jednej rzeczy. Musi posiadać taką właściwość:
public int Id { get; set; }
To przykład konwencji. Jeśli chcemy zmienić sposób przechowywania identyfikatora, należy skorzystać z DocumentStore.Conventions.FindIdentityProperty. Użyty przeze mnie EmbeddableDocumentStore dziedziczy z DocumentStore, a więc jeśli znudzi mi się Id to zawsze mogę to zmienić.

Jeśli chcemy aby Raven DB ignorował niektóre właściwości w czasie zapisywania obiektu to powinniśmy oznaczyć je atrybutem Newtonsoft.Json.JsonIgnore, który działa w taki sam sposób jak XmlIgnore dla XmlSerializer.

Zapisz/Zmień

Operację wstawienia nowego dokumentu do bazy lub aktualizacji już istniejącego wykonuję w taki sam prosty sposób np.:
public void Save(ExpressionEntity ex)
{
 using (var session = Store.OpenSession())
 {
  session.Store(ex);
  session.SaveChanges();
 }
}
Zaczynam, więc od otworzenia sesji pracy z RavenDB. Następnie przy pomocy metody Store wrzucam do bazy nowy dokument lub aktualizuję już istniejący. Jak widać nie przejmuję się, którą operację właściwie wykonuję. Jeśli obiekt będzie miał pusty/zerowy Id to zostanie utworzony nowy dokument, a właściwość Id zostanie uaktualniona. Jeśli Id zostanie wypełnione Raven DB spróbuje odszukać istniejący dokument i go uaktualnić. Jeśli nie znajdzie dokumentu o podanym identyfikatorze utworzy go. Metoda SaveChanges to coś w rodzaju Commit'a: wysyła zmiany do serwera.

Usuń

Usuwanie dokumentów z bazy również jest bardzo proste np.:
public void Remove(ExpressionEntity ex)
{
 using (var session = Store.OpenSession())
 {
  session.Delete<ExpressionEntity>(session.Load<ExpressionEntity>(ex.Id));
  session.SaveChanges();
 }
}
Jak widać przed usunięciem ładuję obiekt z bazy na podstawie identyfikatora. Jest to potrzebne ponieważ inaczej dostaniemy błąd z informacją, że obiekt nie jest doczepiony do sesji (is not associated with the session, cannot delete unknown entity instance). Nie znalazłem innego sposobu rozwiązania problemu.

Ważna uwaga

Powyżej przedstawiłem dwie przykładowe metody Save oraz Remove, które odpowiednio tworzą/aktualizują jeden dokument oraz usuwają jeden dokument z bazy danych. W przypadku wykonywania operacji na wielu dokumentach takie podejście będzie zbyt kosztowne. Jeśli zachodzi potrzeba pracy z wieloma dokumentami to powinniśmy zrezygnować z takiego mikro zarządzania i jak najwięcej operacji wykonywać w ramach jednej sesji.

Podsumowanie

Dzisiaj pokazałem jak wykonywać podstawowe operacje na dokumentach. Jak widać jest to bardzo proste. Właściwie nie musimy nic robić aby nakłonić nasze obiekty do współpracy z Raven DB. Nie potrzebujemy również mappera relacyjno-obiektowego. To jest właśnie to co bardzo mi się spodobało w Raven DB.

Definiuję sobie klasę, tworzę jej instancje i po prostu wrzucam je do bazy danych. Nie piszę komend INSERT, UPDATE lub DELETE. Nie instaluję dodatkowych komponentów. Nie konfiguruję mapowań pomiędzy tabelami i obiektami. Nie definiuję schematu bazy danych. Jest prosto, szybko i przyjemnie czyli tak jak powinno być!

Na koniec znowu podsumujmy co już mamy/umiemy:
  • Bazę Raven DB osadzoną w aplikacji hostującej.
  • Kod inicjalizujący Raven DB.
  • Dostęp do Raven Studio i API REST'owego.
  • Obiekty POCO jakie mogą zostać umieszczone w Raven DB.
  • Kod dodający/zmieniający/usuwający dokumenty.

2 comments:

Anonymous said...

Znalazłem taki sposób na usuwanie bez wcześniejszego pobierania encji:

using (var session = documentStore.OpenSession())
{ session.Advanced.DatabaseCommands.Delete("categories/1", null);
}

Michał Komorowski said...

Dziękuję za wskazówkę, dobrze o tym wiedzieć.