Laden...

Mehrere Services aufrufen und diese in eine Transaction einbinden?

Erstellt von #coder# vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.517 Views
#coder# Themenstarter:in
395 Beiträge seit 2008
vor 12 Jahren
Mehrere Services aufrufen und diese in eine Transaction einbinden?

Hallo, ich habe eine Anwendung die soll z.B. aus dem BusinessLayer ein Objekt mit mehreren Abhängigkeiten speichern. Als Beispiel soll eine **Category **und die **Subcategories **gespeichert werden.
Für die einzelnen Objekte gibt es Service Klassen die jeweileils eine Repository Klasse aus einem weiteren Layer aufrufen.
Wenn eine Category gespeichert wird, müsste folgender Ablauf stattfinden:

Pseudocode:

void CreateCategory(Category category, List<Subcategory> subcategories)
{

  // Hier müsste die Transaction eingeleitet werden
      CategoryService.Save(category);
      SubcategoryService.Save(category.Id, subcategories);
  //Am ende ein Commit

}

Es soll alles atomar gespeichert werden, d.h. es darf nicht die Category gespeichert werden, wenn es ein Fehler bei Subcategories gibt!

Da ich mich im BusinessLayer befinde, darf ich keine Referenz auf SqlTransaction haben, nun wie könnte man sowas lösen, übergibt man ein weiteren Flag, der eine Transaction auf den unteren Schichten einleitet?

2.891 Beiträge seit 2004
vor 12 Jahren

Einfach einen TransactionScope benutzen sollte doch funktionieren, oder?


using (var transactionScope = new TransactionScope())
{
   CategoryService.Save(category);
   SubcategoryService.Save(category.Id, subcategories);

   transactionScope.Commit();
}

Alle gängigen Datenbankprovider unterstützen das. Und wir hier von WCF-Services reden, kannst du auch dort die Transaktionen mit durchschleifen.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo #coder#,

Da ich mich im BusinessLayer befinde, darf ich keine Referenz auf SqlTransaction haben, nun wie könnte man sowas lösen, übergibt man ein weiteren Flag, der eine Transaction auf den unteren Schichten einleitet?

es sollte doch reichen, wenn der Layer, der die Dienste und deren Save-Methoden zur Verfügung stellt, auch entsprechende Methoden zum Einleiten und Abschließen von Transaktionen bereitstellt.

herbivore

N
20 Beiträge seit 2010
vor 12 Jahren

WCF unterstützt verteilte Transaktionen. Allerdings muss dafür ein kompatibles Binding verwendet und die Eigenschaft "transactionFlow" auf true gesetzt werden (üblicherweise in der Service-Web.config).

Darüberhinaus gibt es Attribute um das Transaktionsverhalten zu steuern:*[TransactionFlow( TransactionFlowOption.Mandatory/Allowed/NotAllowed )] über den Methoden im Service-Contract *[OperationBehavior( TransactionScopeRequired = true/false )] über der jeweiligen Methodenimplementierung

Bei TransactionFlowOption.Allowed und TransactionScopeRequired = true wird also beispielsweise automatisch eine lokale Transaktion erzeugt, falls keine durch den Aufrufer übergeben wurde (typischerweise über TransactionScope).

In der Persistenzschicht kann man dann einfach über sqlConnection.Enlist(Transaction.Current) an der übergebenen Transaktion teilnehmen.

#coder# Themenstarter:in
395 Beiträge seit 2008
vor 12 Jahren

Wie sieht es mit **StoredProcedures **und **TransactionScope **aus. Werden nicht über die **TransactionScope **alle DB Operationen in eine Queue gepackt und anschließend die **StoredProcedures **nacheinander aufgerufen? Bei uns werden StoredProcedures für die CRUD Operationen in der DB genutzt.
Wenn z.B. das Beispiel von oben zuerst die **CategoryStoredProcedure **und anschließend die fehlerhafte **SubcategoryStoredProcedure **aufgerufen wird, müsste die Anwendung theoretisch bis zur oberen Schicht eine Exception weitergeben, damit das **.Complete()**nicht aufgerufen wird, richtig? Ansonsten wird die Category gespeichert, was nicht sein sollte.

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo #coder#,

der TransactionScope erstellt eine Transaction in der DB, also wird dort auch Commit und Rollback durchgeführt.

Wenn alle beteiligten Aktionen einen Transaktion unterstützen, so wird entweder alles bestätigt od. zurückgenommen.

Aber probiers einfach aus und schau dir das Verhalten selbst an.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

#coder# Themenstarter:in
395 Beiträge seit 2008
vor 12 Jahren

Danke, es hat funktioniert mit den StoredProcedures. Ich habe neben den TransactionScope auf der oberen Schichten auch im DAL jedem SqlCommand Objekt eine **SqlTransaction ** gesetzt, da es StoredProcedures gibt, die gleich mehrere Tabellen aktualisieren müssen (z.B. Zurodnungstabellen). Danke für die Hilfe!