Entity Framework 6 und Unit of Work… Wo, wann? Ist es wie Transaktionen in ado.net

Ein neues MVC-Projekt erstellen und die Idee von Repositorys in der Datenschicht mögen, also habe ich sie implementiert. Ich habe auch eine Service-Ebene erstellt, die die gesamte Geschäftslogik und -validierung abwickelt. Diese Ebene verwendet wiederum das entsprechende Repository. So etwas (ich benutze Simple Injector zum Injizieren)

DAL LAYER

public class MyRepository {

    private DbContext _context;
    public MyRepository(DbContext context) {
        _context = context;
    }    

    public MyEntity Get(int id)
    {
        return _context.Set<MyEntity>().Find(id);
    }

    public TEntity Add(MyEntity t)
    {
        _context.Set<MyEntity>().Add(t);
        _context.SaveChanges();
        return t;
    }

    public TEntity Update(MyEntity updated, int key)
    {
        if (updated == null)
            return null;

        MyEntity existing = _context.Set<MyEntity>().Find(key);
        if (existing != null)
        {
            _context.Entry(existing).CurrentValues.SetValues(updated);
            _context.SaveChanges();
        }
        return existing;
    }

    public void Delete(MyEntity t)
    {
        _context.Set<MyEntity>().Remove(t);
        _context.SaveChanges();
    }
}

SERVICE LAYER

public class MyService {
    private MyRepository _repository;

    public MyService(MyRepository repository) {
        _repository = repository;    
    }

    public MyEntity Get(int id)
    {
        return _repository.Get(id);
    }

    public MyEntity Add(MyEntity t)
    {
        _repository.Add(t);

        return t;
    }

    public MyEntity Update(MyEntity updated)
    {
        return _repository.Update(updated, updated.Id);
    }

    public void Delete(MyEntity t)
    {
        _repository.Delete(t);
    }
}

Now das ist sehr einfach, so kann ich den folgenden Code verwenden, um ein Objekt zu aktualisieren.

MyEntity entity = MyService.Get(123);
MyEntity.Name = "HELLO WORLD";
entity = MyService.Update(entity);

Oder dies, um ein Objekt zu erstellen

MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
// entity.Id is now populated

Nun muss ich sagen, dass ich ein Element basierend auf der Erstellungs-ID eines anderen aktualisieren muss, ich könnte den Code vor allem gut verwenden, aber was passiert, wenn ein Fehler auftritt? Ich brauche eine Art Transaktion / Rollback. Ist es das Muster der Arbeitseinheit, das gelöst werden soll?

So denke ich, dass ich DbContext in meinem UnitOfWork-Objekt haben muss, also erstelle ich ein Objekt wie dieses?

public class UnitOfWork : IDisposable {

    private DbContext _context;

    public UnitOfWork(DbContext context) {
        _context = context;
    }

    public Commit() {
        _context.SaveChanges();
    }

    public Dispose() {
        _context.Dispose();
    }

}

Ok also nochmal, das ist ganz einfach. UnitOfWork enthält auch den Kontext (ich verwende sowieso denselben Kontext für alle Repositorys) und ruft die SaveChanges () -Methode auf. Ich würde dann den Methodenaufruf SaveChanges () aus meinem Repository entfernen. Also, um hinzuzufügen, würde ich Folgendes tun:

UnitOfWork uow = new UnitOfWork(new DbContext()); // i would inject this somehow

MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);

uow.Commit();

Aber was ist, wenn ich ein Objekt erstellen und dann andere Objekte basierend auf dieser ID aktualisieren muss, funktioniert dies jetzt nicht, da die ID erst erstellt wird, wenn ich Commit auf der uow aufrufe. Beispie

UnitOfWork uow = new UnitOfWork(new DbContext()); // i would inject this somehow

MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
// entity.Id is NOT populated

MyEntity otherEntity = MyService.Get(123);
otherEntity.OtherProperty = entity.Id;
MyService.Update(otherEntity);

uow.Commit();  // otherEntity.OtherProperty is not linked.....?

So habe ich das Gefühl, dass diese UnitOfWork-Klasse nicht richtig ist ... vielleicht verstehe ich etwas nicht.

Ich muss in der Lage sein, eine Entität hinzuzufügen und diese ID abzurufen und für eine andere Entität zu verwenden, aber wenn ein Fehler auftritt, möchte ich ein Rollback durchführen, wie dies bei einer ado.net-Transaktion der Fall wäre.

Ist diese Funktionalität mit Entity Framework und Repositories möglich?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage