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.
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