Frage

Wir entwickeln eine .NET -Anwendung mit der folgenden Architektur: Präsentationsschicht (unter Verwendung des MVC -Musters mit ASP.NET MVC 2), Service -Schicht, Datenzugriffsschicht (mithilfe von Repository -Muster über Entity -Framework).

Wir haben uns entschlossen, das Transaktionsmanagement in die Serviceebene zu setzen, aber wir sind uns nicht sicher, wie sie implementiert werden sollen. Wir möchten die Transaktion vollständig auf der Serviceebene steuern. Jedes Mal, wenn ein Controller eine Methode in der Serviceschicht aufruft, muss es sich um eine Atomoperation in Bezug auf Datenbankaktualisierungen handeln.

Wenn es keinen Zusammenhang zwischen verschiedenen Diensten in der Serviceschicht gäbe, wäre dies einfach: Jede Methode sollte die Änderungen am Ende ihrer Ausführung begehen (dh die Speichernmethode auf dem von ihnen verwendeten Kontext). Aber manchmal arbeiten die Dienstleistungen auf der Serviceschicht zusammen.

ZB: Wir bieten einen Sendungsservice mit einer Bestätigungsmethode, die die folgenden Parameter erhält: die Versand -ID, ein Flag, das angibt, ob es einem neuen Kunden oder einer vorhandenen, die Kunden -ID entspricht (falls die Versandbestätigung für eine vorhandene Bestätigung gilt Kunde) und ein Kundenname (falls dies für einen neuen Kunden gilt). Wenn das Flag auf "New Customer" eingestellt ist, muss die Serviceschicht (a) den Kunden erstellen und (b) die Sendung bestätigen. Für (a) ruft der Versanddienst den Kundendienst auf (der bereits die Validierungen und die Logik implementiert, um einen neuen Kunden zu erstellen und in der Datenbank zu speichern).

Wer sollte die Änderungen in diesem Szenario begehen?

  • Sollte der Kundendienst das tun? Es kann die Änderungen nach dem Erstellen des neuen Kunden nicht begehen, da etwas später in der Sendungsbestätigungsmethode schief gehen kann, aber es muss seine Änderungen in dem Fall festlegen, dass es direkt aufgerufen wird (in anderen Anwendungsfällen, die für die Erstellung eines Kunden bereitgestellt werden).
  • Sollte der Controller die Servicemethode aufruft? Aber der Controller sollte nichts über Transaktionen wissen, wir haben beschlossen, alle Transaktionen in der Serviceschicht zu setzen.
  • Ein Transaktionsleiter in der Diensteschicht? Wie kann man es entwerfen? Wer nennt es und wann?

Gibt es ein Designmuster dafür, dem wir folgen sollten?

War es hilfreich?

Lösung

Ich habe ein Commit () in meinem Dienst. Dies verpflichtet sich nur, wenn das UnitOfwork vom Dienst erstellt wird, wenn es im Konstruktor verabschiedet wird, tut das Commit nichts.

Ich habe einen zweiten (internen) Konstruktor für den Dienst verwendet:

public class MyService
{
private IUnitOfWork _uow;
private bool _uowInternal;

public MyService()
{
    _uow = new UnitOfWork();
    _uowInternal = false;
}

internal MyService(IUnitOfWork uow)
{
    _uow = uow;
    _uowInternal = true;
}
public MyServiceCall()
{
    // Create second service, passing in my UnitOfWork:
    var svc2 = new MySecondService(_uow);

    // Do your stuff with both services.
    ....
    // Commit my UnitOfWork, which will include all changes from svc2:
    Commit();
}

public void Commit()
{
    if(!_uowInternal)
        _uow.Commit();
}
}

Andere Tipps

In einer ähnlichen Architektur mit WCF und L2S anstelle von EF haben wir uns für Transaktionen in der Implementierungsklasse der wichtigsten Serviceschnittstelle entschieden. Wir verwendeten Transactionscope um das zu erreichen:

public void AServiceMethod() {
    using(TransactionScope ts = new TransactionScope()) {
         service1.DoSomething();
         service2.DoSomething();
         ts.Complete();
    }
}

Der Hauptnachteil ist, dass die Transaktion möglicherweise groß wird. In diesem Fall müssen wir beispielsweise nur einer der Serviceaufrufe im Transaktionsblock nur merkwürdig zugreifen TransactionScope(TransactionScopeOption.Suppress) Blockieren Sie, um die Verriegelungszeilen/Tabellen weiter in der Transaktionslebensdauer zu verhindern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top