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.

Listing 4<br />

Ein Update überprüfen.<br />

[TestFixture]<br />

public class ProductRepositoryTests<br />

{<br />

private ProduktRepository sut;<br />

[SetUp]<br />

public void Setup() {<br />

sut = new ProduktRepository();<br />

}<br />

}<br />

[Test]<br />

public void Ein_Produkt_ändern() {<br />

var produkt = new Produkt {<br />

Id = "#1",<br />

Name = "iPad",<br />

Kategorie = "Zeugs"<br />

};<br />

sut.Save(produkt);<br />

produkt.Kategorie = "Gadget";<br />

sut.Save(produkt);<br />

}<br />

var result = sut.Load("#1");<br />

Assert.That(result.Kategorie,<br />

Is.EqualTo("Gadget"));<br />

schende Objekt übergeben wird. Dabei<br />

stellte sich mir die Frage, wie man ein Dokument<br />

aus der Datenbank löscht, dessen<br />

Id man kennt, das aber nicht als Objekt geladen<br />

wurde. Natürlich kann man das Objekt<br />

zuerst über seine Id laden, um es dann<br />

an Delete zu übergeben. Dabei fallen aber<br />

zwei Zugriffe auf den Server an, das sollte<br />

doch auch mit einem Zugriff zu machen<br />

sein. Das Löschen über die Id ist im Client-<br />

API nicht vorgesehen. Das bedeutet aber<br />

nicht, dass es unmöglich ist. Das Client-API<br />

ist nur ein Wrapper, der über das HTTP-<br />

Protokoll gelegt ist, und in diesem API ist<br />

Löschen per Id nicht vorgesehen. Wie man<br />

das API erweitert, habe ich mir allerdings<br />

in diesem Spike nicht weiter angesehen.<br />

Konkurrierende Zugriffe<br />

Beim Erforschen des APIs ist mir an dieser<br />

Stelle die Frage gekommen, wie RavenDB<br />

sich bei konkurrierenden Zugriffen verhält.<br />

Damit meine ich Zugriffe, die in zwei unterschiedlichen<br />

Sessions stattfinden. Stellen<br />

Sie sich dazu eine Anwendung vor, von der<br />

mehrere Instanzen laufen. Was passiert,<br />

wenn ein Dokument aus der Datenbank von<br />

beiden Anwendern geladen und verändert<br />

wird. Merkt RavenDB das beim Update? Um<br />

die Frage zu klären, habe ich einen Test geschrieben.<br />

Um dabei mit zwei Sessions ar-<br />

beiten zu können, habe ich die Sessions ineinandergeschachtelt.<br />

Das heißt, während<br />

die erste Session noch aktiv ist, wird innerhalb<br />

des using-Blocks eine zweite Session<br />

geöffnet, um dort ein Update vorzunehmen.<br />

Dann wird aus der ersten Session<br />

ebenfalls ein Update abgesetzt.<br />

Listing 5<br />

Das Repository implementieren.<br />

Das Verhalten von RavenDB hängt an<br />

dieser Stelle davon ab, ob die Session Optimistic<br />

Concurrency unterstützen soll. Dies<br />

kann man per Session einstellen, standardmäßig<br />

ist es abgestellt. Das bedeutet, wenn<br />

man keine weitere Vorkehrung trifft, werden<br />

Konflikte bei konkurrierenden Zugrif-<br />

public class ProduktRepository {<br />

private readonly DocumentStore store;<br />

public ProduktRepository() {<br />

store = new DocumentStore {Url = "http://localhost:8080"};<br />

store.Initialize();<br />

}<br />

public void Save(Produkt produkt) {<br />

using (var session = store.OpenSession()) {<br />

session.Store(produkt);<br />

session.SaveChanges();<br />

}<br />

}<br />

public Produkt Load(string id) {<br />

using (var session = store.OpenSession()) {<br />

var result = session.Load(id);<br />

return result;<br />

}<br />

}<br />

}<br />

Listing 6<br />

Konkurrierende Zugriffe erkennen.<br />

[Test]<br />

public void Optimistic_Concurrency_bei_Updates_in_mehreren_Sessions() {<br />

var store = new DocumentStore {Url = "http://localhost:8080"};<br />

store.Initialize();<br />

// Initialzustand der Datenbank herstellen<br />

var produkt = new Produkt {Name = "a"};<br />

using (var session = store.OpenSession()) {<br />

session.Store(produkt);<br />

session.SaveChanges();<br />

}<br />

// Erste Session lädt das Dokument als 'referenz1'<br />

using (var session1 = store.OpenSession()) {<br />

session1.UseOptimisticConcurrency = true;<br />

var referenz1 = session1.Load(produkt.Id);<br />

// Zweite Session lädt das Dokument als 'referenz2'<br />

// und modifiziert es<br />

using (var session2 = store.OpenSession()) {<br />

var referenz2 = session2.Load(produkt.Id);<br />

Assert.That(referenz2, Is.Not.SameAs(referenz1));<br />

referenz2.Name = "b";<br />

session2.SaveChanges();<br />

}<br />

// 'referenz1' hat die Änderungen aus der zweiten<br />

// Session noch nicht gesehen, daher Bumm!<br />

referenz1.Name = "c";<br />

Assert.Throws(session1.SaveChanges);<br />

}<br />

}<br />

LÖSUNG<br />

www.dotnetpro.de dotnetpro.dojos.2011 35

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

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!