2016-03-22 16 views
0

Ich habe gelesen, dass Dapper ist viel schneller als EF im Allgemeinen und dachte über die Verwendung von Dapper für die Abfrageseite und EF für die Schreibseite einer Anwendung mit dem CQRS (Lite) -Muster.EF lesen und schreiben Modi für CQRS

Ich bin mir aber auch bewusst, dass EF die Verfolgung standardmäßig deaktivieren kann. Lohnt es sich, zwei Datenbankkontexte zu erstellen, einen für das Lesen mit aktiviertem AsNoTracking für alle Entitäten und einen für das Schreiben mit aktiviertem Tracking? Auf diese Weise habe ich den Leistungsvorteil, ohne eine andere Bibliothek zu verwenden und zusätzliche Komplexität hinzuzufügen.

+0

Wie würden Sie 'AsNoTracki aktivieren? ng 'kontext-weit? –

+0

Ich denke nicht, dass dies aus der Box kommt, aber es kann getan werden. http://stackoverflow.com/questions/12726878/global-setting-for-asnotracking – user183872

Antwort

2

Wie für Entity Framework, sollten Sie nur eine DbContext in Ihrer Anwendung haben.

Sie können mit einer einfachen Abstraktion von Ihrem Kontext betrachten Sie eine Lese-Seite und eine Schreib-Seite zu geben:

public abstract class Entity 
{ 
    // Marker class 
} 

public interface IEntityReader<out TEntity> where TEntity : Entity 
{ 
    IQueryable<TEntity> Query(); 
} 

public interface IEntityWriter<TEntity> where TEntity : Entity 
{ 
    TEntity Get(object primaryKey); 

    void Save(TEntity entity); 

    void Delete(TEntity entity); 
} 

Mit der Umsetzung fo diese wie:

internal sealed class EntityFrameworkReader<TEntity> : IEntityReader<TEntity> where TEntity : Entity 
{ 
    private readonly Func<DbContext> _contextProvider; 

    public EntityFrameworkReader(Func<DbContext> contextProvider) 
    { 
     _contextProvider = contextProvider; 
    } 

    public IQueryable<TEntity> Query() 
    { 
     return _contextProvider().Set<TEntity>().AsNoTracking(); 
    } 

} 

internal sealed class EntityFrameworkWriter<TEntity> : IEntityWriter<TEntity> where TEntity : Entity 
{ 
    private readonly Func<DbContext> _contextProvider; 

    public EntityFrameworkWriter(Func<DbContext> contextProvider) 
    { 
     _contextProvider = contextProvider; 
    } 

    public void Save(TEntity entity) 
    { 
     var context = _contextProvider(); 
     var entry = context.Entry(entity); 

     // If it is not tracked by the context, add it to the context 
     if (entry.State == EntityState.Detached) 
     { 
      // This also sets the entity state to added. 
      context.Set<TEntity>().Add(entity); 
     } 
     else 
     { 
      // Tells the context that the entity should be updated during saving changes 
      entry.State = EntityState.Modified; 
     } 

     // In a perfect world, you should use a decorator and save the changes there using Dependency Injection 
     context.SaveChanges(); 
    } 

    public void Delete(TEntity entity) 
    { 
     var context = _contextProvider(); 
     var entry = context.Entry(entity); 
     if (entry.State != EntityState.Deleted) 
     { 
      // This also sets the entity state to Deleted. 
      context.Set<TEntity>().Remove(entity); 
     } 

     // In a perfect world, you should use a decorator and save the changes there using Dependency Injection 
     context.SaveChanges(); 
    } 

    public TEntity Get(object primaryKey) 
    { 
     var context = _contextProvider(); 
     var entity = context.Set<TEntity>().Find(primaryKey); 
     if (entity == null) return null; 

     // We found the entity, set the state to unchanged. 
     context.Entry(entity).State = EntityState.Unchanged; 

     return entity; 
    } 
} 

Wenn Sie mit Eine Abhängigkeitsinjektions-Bibliothek, wie Simple Injector, können Sie wie folgt verdrahten:

container.Register<DbContext, MyDbContext>(Lifestyle.Scoped); 
container.Register(typeof(IEntityWriter<>), typeof(EntityFrameworkWriter<>), Lifestyle.Scoped); 
container.Register(typeof(IEntityReader<>), typeof(EntityFrameworkReader<>), Lifestyle.Scoped); 
+0

Das sieht gut aus! Also würde ein bestimmtes Repository entweder von einem Writer oder Reader erben, der dann die korrekte Funktionalität bietet? – user183872

+0

Sie können 'IEntityWriter ' immer verwenden, wenn Sie Entitäten schreiben müssen. Keine Notwendigkeit für ein bestimmtes Repository :-) – janhartmann