2009-06-18 15 views
1

Ich habe einige C# -Code, der wie dieserSoftware Transaktionen in C#

D d = new D(); 
foreach(C item in list) 
{ 
    c.value++; 
    d.Add(c); // c.value must be incremented at this point 
} 
if(!d.Process()) 
    foreach(C item in list) 
     c.value--; 

Es Wert in einer Liste für jedes Element erhöht arbeiten muss und dann versucht, auf sie einige Verarbeitung zu tun. Wenn die Verarbeitung fehlschlägt, muss die Mutation oder die Elemente verdunkelt werden.

Die Frage ist: gibt es eine bessere Möglichkeit, dies zu tun? Die Dinge, die ich nicht mag ist, dass es Möglichkeiten gibt, wie ich sehen kann, dass es schief geht. Zum Beispiel, wenn etwas über alles wirft es nicht mehr synchron ist.

Eine Idee (das scheint fast noch schlimmer als das Problem) ist:

D d = new D(); 
var done = new List<C>(); 
try 
{ 
    foreach(C item in list) 
    { 
     c.value++; 
     done.Add(c); 
     d.Add(c); 
    } 
    if(d.Process()) done.Clear(); 
} 
finaly 
{ 
    foreach(C c in done) 
     c.value--; 
} 

Antwort

1

Es ist sehr speicherintensiv, aber Sie können, bevor das Zunehmen eine Kopie der Liste zu machen. Wenn der Prozess erfolgreich ist, können Sie die neue Liste zurückgeben. Wenn dies fehlschlägt, geben Sie die ursprüngliche Liste zurück.

+0

Ich arbeite mit Referenz-Semantik, so dass es nicht funktioniert, wenn ich eine tiefe Kopie mache und selbst dann es funktioniert möglicherweise nicht, wenn es andere Verweise auf die Elemente gibt. – BCS

0

Warum erhöhen Sie nicht nur, wenn der Prozess erfolgreich ist?

Ich denke, ein besserer Weg ist, die Prozessmethode in D erhöht den c.value innerhalb.

+0

siehe Bearbeiten/Kommentar. Daraus ergibt sich, dass es sich um Shim-Code handelt, der in einer bestehenden Umgebung mit diesen Anforderungen arbeiten muss. – BCS

2

Ohne die vollständigen Details Ihrer Anwendung zu kennen, glaube ich nicht, dass es möglich ist, Ihnen eine konkrete Lösung für das Problem zu geben. Grundsätzlich gibt es keine Methode, die immer in 100% der Situationen funktioniert, in denen Sie so etwas brauchen.

Aber wenn Sie die Kontrolle über die Klasse haben und sich der Umstände bewusst sind, in denen D.Process() fehlschlagen wird, können Sie möglicherweise eines von zwei Dingen tun, die dieses Konzept einfacher zu verwalten machen.

Eine Möglichkeit ist D ‚s Zustand vor dem Aufruf die Process Methode durch so etwas wie eine CanProcess Funktion zu testen, implementieren, wenn und nur wenn Process true zurück würde, aber ohne tatsächlich etwas zu verarbeiten.

Eine andere Möglichkeit besteht darin, ein temporäres D-Objekt zu erstellen, das nicht tatsächlich festschreibt, sondern die Process-Methode auf ihrem Inhalt ausführt. Dann, wenn Process erfolgreich war, rufen Sie eine Art von Promote oder Commit Methode auf, die die Änderungen abschließt. Ähnlich wie wenn Sie ein Objekt Dataset hätten, können Sie einen Klon daraus erstellen, Ihre Transaktionsdaten im Klon ausführen und sie dann genau dann wieder in das Hauptdatenset einfügen, wenn die Verarbeitung erfolgreich war.

+0

Ich würde gerne # 1 tun, aber ich kann die "Verarbeitbarkeit" Situation aus unter mir ändern. Das gleiche Problem mit # 2; Ich würde es gerne machen, aber in meinem Fall wird es nicht funktionieren. (D.Process trifft einen Netzwerkdienst, der keine Sperren zwischen Anrufen halten soll) – BCS

+0

Haben Sie die Kontrolle über diesen Netzwerkdienst überhaupt? – Welbog

+0

Der Dienst selbst? Ja. Der Back-End-Code, auf den der Service trifft? Ein bisschen, aber nicht wirklich. Ich würde lieber nicht damit herumärgern, wie es auch von anderem Code genannt wird, den ich nicht wirklich verstehe. – BCS