b2aat6n
b2aat6n
b2aat6n
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Build verfügbar, daher bietet sich in anderen<br />
Fällen die Arbeit mit den Quellen an.<br />
Nach dem Download stand mir RavenDB<br />
nun zur Verfügung. Ich habe es komplett in<br />
das lib-Verzeichnis innerhalb der Projektstruktur<br />
abgelegt. Damit unterliegt es der<br />
Versionierung, und das Projekt ist in sich<br />
abgeschlossen.<br />
Client und Server<br />
RavenDB kann auf verschiedenen Wegen<br />
verwendet werden: eingebettet in die Anwendung<br />
oder getrennt in Client und Server.<br />
Ich entschied mich dafür, RavenDB als<br />
Server zu starten. Im Implementierungsprojekt<br />
muss dann nur die Assembly Raven.Client.Lightweight.dll<br />
aus dem Client-<br />
Verzeichnis referenziert werden. Der Server<br />
befindet sich im Verzeichnis Server. Klingt<br />
logisch, oder? Dennoch sind solche klaren<br />
Strukturen nicht selbstverständlich. Oft befinden<br />
sich alle binären Artefakte eines<br />
Frameworks gemeinsam in einem bin-Verzeichnis,<br />
aus dem man sich selbst heraussuchen<br />
muss, was man benötigt. Da gefällt<br />
mir diese Aufteilung bei RavenDB doch<br />
sehr gut. Sie vereinfacht die ersten Schritte.<br />
Doch zurück zum Server. Der kann innerhalb<br />
eines IIS gehostet werden oder<br />
auch als Windows-Dienst laufen. Ich habe<br />
nur den Windows-Dienst ausprobiert. Dazu<br />
muss man zwei Befehle ausführen:<br />
❚ RavenDb.exe /install<br />
❚ RavenDb.exe /start<br />
Der erste Befehl installiert RavenDB als<br />
Windows-Dienst, der zweite startet den<br />
Dienst. Weil das Installieren und Starten von<br />
Diensten unterWindows nicht jedem Nutzer<br />
erlaubt sind, kümmert sich RavenDB bei<br />
Bedarf um die Elevation, also das Beschaffen<br />
der nötigen Rechte. Das ist vorbildlich!<br />
Statt eine kryptische Fehlermeldung auszugeben,<br />
eventuell mit dem Hinweis, man<br />
möge das Programm als Administrator starten,<br />
wird’s mir hier sehr einfach gemacht.<br />
CRUDe Methoden<br />
Nun möchte ich als Erstes ein Objekt in der<br />
RavenDB-Datenbank abspeichern. Dazu<br />
habe ich die Klasse Produkt angelegt. Die<br />
Klasse berücksichtigt keine Infrastruktur,<br />
Instanzen sind sogenannte POCOs: Plain<br />
Old CLR Objects. Damit wird im Allgemeinen<br />
die sogenannte Infrastrukturignoranz<br />
bezeichnet. RavenDB stellt (fast) keine Anforderungen<br />
an eine zu persistierende<br />
Klasse. Es muss nicht von einer Basisklasse<br />
abgeleitet werden, es muss kein spezielles<br />
Interface implementiert werden, und es<br />
sind keine Attribute erforderlich. Nur eine<br />
Konvention ist einzuhalten: RavenDB benötigt<br />
eine Eigenschaft namens Id vom Typ<br />
string. In dieser Eigenschaft wird der eindeutige<br />
Schlüssel des Objekts von RavenDB<br />
erwartet. Natürlich kann diese Konvention<br />
geändert werden, wenn sie nicht passt.<br />
public class Produkt {<br />
public string Id { get; set; }<br />
public string Name { get; set; }<br />
public string Kategorie { get; set;<br />
}<br />
Um eine Instanz der Klasse mit RavenDB<br />
zu persistieren, benötigt man einen sogenannten<br />
DocumentStore. Dieser sollte pro<br />
Anwendung nur einmal erzeugt werden.<br />
Mithilfe des DocumentStore wird eine Do-<br />
Listing 2<br />
RavenDB sichert die Objektidentität.<br />
LÖSUNG<br />
cumentSession erzeugt. Innerhalb einer<br />
Session werden Änderungen vorgenommen<br />
und am Ende persistiert. Listing 1<br />
zeigt das Speichern eines Objektes.<br />
Der DocumentStore enthält keinen Zustand,<br />
dafür ist die DocumentSession zuständig.<br />
Während der Lebenszeit der Session<br />
sorgt diese für die Objektidentität:<br />
Wird ein und dasselbe Dokument mehrfach<br />
aus der Datenbank geladen, liefert die<br />
Session jeweils ein und dasselbe Objekt. So<br />
ist sichergestellt, dass innerhalb einer<br />
Session nur genau eine Instanz eines Dokumentes<br />
der Datenbank existiert. Ohne<br />
diese Objektidentität wäre die Gefahr sehr<br />
groß, dass an unterschiedlichen Objekten<br />
Änderungen vorgenommen werden, die<br />
[Test]<br />
public void Session_stellt_Objektidentität_sicher() {<br />
var store = new DocumentStore {Url = "http://localhost:8080"};<br />
store.Initialize();<br />
var produkt = new Produkt();<br />
using (var session = store.OpenSession()) {<br />
session.Store(produkt);<br />
session.SaveChanges();<br />
var produkt2 = session.Load(produkt.Id);<br />
Assert.That(produkt2, Is.SameAs(produkt));<br />
var produkt3 = session.Load(produkt.Id);<br />
Assert.That(produkt3, Is.SameAs(produkt));<br />
}<br />
using (var session = store.OpenSession()) {<br />
var produkt2 = session.Load(produkt.Id);<br />
Assert.That(produkt2, Is.Not.SameAs(produkt));<br />
}<br />
}<br />
Listing 3<br />
Jedes Objekt erhält eine eigene Id.<br />
[Test]<br />
public void Id_wird_durch_Save_erzeugt_aber_Entity_noch_nicht_gespeichert() {<br />
var store = new DocumentStore {Url = "http://localhost:8080"};<br />
store.Initialize();<br />
var produkt = new Produkt();<br />
Assert.That(produkt.Id, Is.Null);<br />
using (var session = store.OpenSession()) {<br />
session.Store(produkt);<br />
}<br />
Assert.That(produkt.Id, Is.Not.Null);<br />
Produkt result;<br />
using (var session = store.OpenSession()) {<br />
result = session.Load(produkt.Id);<br />
}<br />
Assert.That(result, Is.Null);<br />
}<br />
www.dotnetpro.de dotnetpro.dojos.2011 33