15.02.2013 Aufrufe

b2aat6n

b2aat6n

b2aat6n

MEHR ANZEIGEN
WENIGER ANZEIGEN

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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!