2 Stimmen

DbContext Injection in WCF-Dienst

Ich möchte Sie fragen, ob meine Idee gut funktionieren wird.

Ich habe kürzlich damit begonnen, Entity Framework und WCF zu verwenden. In meinem aktuellen Projekt möchte ich jeden Service atomar haben, das heißt, ein Service in einer Transaktion. Aber ich möchte nicht den gleichen Transaktionscode für alle Service-Vorgänge mehrmals schreiben. Dann kam mir die Idee, dass die Transaktion und deren Fehlerbehandlung an einem Ort wie im Code-Schnipsel unten in IOperationInvoker durchgeführt werden.

Der Vorteil dieses Tricks ist, dass ich DbContext instanziieren oder die Transaktion im using-Block erstellen kann, sodass sie unabhängig vom Geschehen im Service sicher entsorgt werden. und ich muss die db-bezogene Ausnahme nur einmal behandeln.

Es scheint zu funktionieren. aber ich mache mir Sorgen, ob dies eine legitime Art ist, IOperationInvoker und EF zu verwenden.

Gibt es Nachteile?

// Dienst-Basisklasse
public abstract MyBaseService
{
    DbContext Datenbank {get; set;}
}

[ServiceContract]
public Schnittstelle IMyService {...}

// konkrete Dienstklasse
public class MyService : MyBaseService, IMyService {...}

public class MyOperationInvoker : IOperationInvoker
{
    IOperationInvoker originalOperationInvoker; // beim Bau zu setzen

    public object Invoke(object Instanz, object[] Eingaben, out object[] Ausgaben)
    {
        using (var dbContext = new MyDbContext())
        {
            // Inject DbContext in meinen Dienst, um ihn zu verwenden.
            (MyServiceBase)Instanz.Datenbank = dbContext;

            // Einen Dienst innerhalb einer db-Transaktion aufrufen.
            using (var Transaktion = dbContext.Database.BeginTransaction())
            {
                try
                {
                    objct ret = originalOperationInvoker.invoke(Instanz, Eingaben, Ausgaben);
                    Transaktion.Commit();
                    return ret;
                }
                catch (Exception e)
                {
                    Transaktion.Rollback();
                    throw;
                }
            }
        }
    }
    ...
}

2voto

usr Punkte 164863

Bei Verwendung eines Operation Invokers: Ja, das kannst du tun. Dies ist der Hauptort, um "Wrapper-Logik" um eingehende Aufrufe in WCF hinzuzufügen. Beachte, dass du für async Methoden eine andere Reihe von Interface-Methoden implementieren musst.

Zur automatischen Transaktionsverwaltung: Ich finde implizite Transaktionen unzureichend, weil du die Isolationsstufe und Timeout-Einstellungen steuern musst. Manchmal benötigst du auch mehrere Transaktionen. Vielleicht nicht in der ersten Version, aber schließlich wirst du dieses Schema überschreiten.

Was ich kürzlich erfolgreich gemacht habe, war die Erstellung einer Klasse, die einen DbContext und eine Transaktion in einer Einheit umhüllt. Die meisten meiner WCF-Methoden sehen so aus:

void SomeMethod() {
 using (var db = new MyDatabaseContext(isolationLevel, timeout, connectionString, ...)) {
  //individueller Inhalt, der den umhüllten DbContext verwendet
  db.CompleteTransaction();
 }
}

Es gibt hier ein wenig Code-Duplizierung, aber es ist nicht zu schlimm und ich habe immer noch die totale Kontrolle darüber, wie ich die Datenbank verwende. Ich könnte mehrere Transaktionen pro Methode verwenden, sie verschachteln oder einen zur Laufzeit berechneten Timeout-Wert verwenden. Hier passiert kein Zauber (wie ein implizit aufgerufener Operation Invoker). Es ist auch sicher vor Ausnahmen.

2voto

Wiktor Zychla Punkte 45367

Ein weiterer Gedanke ist, einen benutzerdefinierten Instanzanbieter zu haben. Der Instanzanbieter ermöglicht es Ihnen, die Lebensdauer von WCF-Serviceinstanzen zu kontrollieren, indem Sie explizite Punkte angeben, an denen die Instanz erstellt und freigegeben wird.

Indem Sie dies mit einem IoC-Container kombinieren, können Sie Ihren Kontext automatisch in den Dienst injizieren lassen und dann entsorgen, wenn die Anfrage abgeschlossen ist.

Ich habe kürzlich darüber gebloggt, lesen Sie meinen Blogeintrag für technische Details.

http://www.wiktorzychla.com/2014/02/lifetime-management-of-wcf-services.html

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X