2016-03-22 6 views
0

Я читал, что Dapper намного быстрее, чем EF, и думал об использовании Dapper для стороны запроса и EF для стороны записи приложения с использованием шаблона CQRS (lite).Режимы чтения и записи EF для CQRS

Однако я также знаю, что EF имеет возможность отключить отслеживание по умолчанию. Стоит ли создавать 2 контекста базы данных, один для чтения с включенным AsNoTracking для всех объектов, а один для записи с включенным отслеживанием? Таким образом, я получаю преимущество в производительности, не используя другую библиотеку и добавляя дополнительную сложность.

+0

Как бы вы включили 'AsNoTracki ng' в контексте? –

+0

Я не думаю, что это получается из коробки, но это можно сделать. http://stackoverflow.com/questions/12726878/global-setting-for-asnotracking – user183872

ответ

2

Что касается Entity Framework, в вашем приложении должен быть только один DbContext.

Вы можете рассмотреть возможность использования простой абстракции вашего контекста, чтобы дать вам чтения и сторону записи:

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); 
} 

При реализации Fo эти как:

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; 
    } 
} 

Если вы используете библиотека инжекционной зависимости, например Simple Injector, вы можете подключить ее так:

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

Это выглядит великолепно! Таким образом, конкретный репозиторий либо наследует от Writer или Reader, который затем предоставляет правильную функциональность? – user183872

+0

Вы можете просто использовать 'IEntityWriter ' когда вам нужно писать объекты. Нет необходимости в конкретном репозитории :-) – janhartmann