2016-12-12 10 views
0

Мой общий репозиторий интерфейс:как ждать вторую операцию на моем контексте, прежде чем первый завершается образ жизни PerWebRequest для контекста и асинхронных вызовов к нему

public interface IGenericRepository<T , TEntityKey> where T : EntityBase<TEntityKey> 
{ 
    IEnumerable<T> GetAll(); 
    IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate); 
    T FindBy(TEntityKey entityKey); 
    Task<T> FindByAsync(TEntityKey entityKey); 
    T Add(T entity); 
    T Delete(T entity); 
    void Edit(T entity); 
    void Save(); 
    void Dispose(); 
} 

Я использовал await для всех методов асинхронными в реализации своих хранилищ. с использованием Castle Windsor в качестве контейнера IOC, я установил свой контекст с помощью PerWebRequestLifeStyle.

Клиент посылает два запроса, и каждый запрос карты для различных хранилищ, реализованных IGenericRepository и это исключение поднимается:

Вторая операция началась на этом контексте перед предыдущей асинхронной операцией завершены. Используйте «ждут», чтобы убедиться, что какие-либо асинхронные операции были выполнены до вызова другого метода в этом контексте. Любые члены экземпляра не гарантируют безопасность потоков.

Я изменил образ жизни контекста на переходный, но все же исключение. Может ли кто-нибудь помочь, где я ошибаюсь?

GenericRepository Реализация:

public abstract class GenericRepository<T, TEntityKey> : IGenericRepository<T, TEntityKey> 
    where T : EntityBase<TEntityKey> 
{ 
    protected IDbContext _entities; 
    protected readonly IDbSet<T> _dbset; 

    protected GenericRepository(IDbContext context) 
    { 
     _entities = context; 
     _dbset = _entities.Set<T>(); 
    } 

    ~GenericRepository() 
    { 
     _entities.Dispose(); 
    } 

    public virtual IEnumerable<T> GetAll() 
    { 
     return _dbset.AsEnumerable<T>(); 
    } 

    public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate) 
    { 

     IEnumerable<T> query = _dbset.Where(predicate).AsEnumerable(); 
     return query; 
    } 

    public T FindBy(TEntityKey entityKey) 
    { 
     var result = _dbset.SingleOrDefault(e => e.Id.ToString() == entityKey.ToString()); 
     return result; 
    } 

    public Task<T> FindByAsync(TEntityKey entityKey) 
    { 
     var result = _dbset.SingleOrDefaultAsync(e => e.Id.ToString() == entityKey.ToString()); 
     return result; 
    } 

    public virtual T Add(T entity) 
    { 
     return _dbset.Add(entity); 
    } 

    public virtual T Delete(T entity) 
    { 
     return _dbset.Remove(entity); 
    } 

    public virtual void Edit(T entity) 
    { 
     _entities.Entry(entity).State = EntityState.Modified; 
    } 

    public virtual void Save() 
    { 
     _entities.SaveChanges(); 
    } 

    public async Task SaveAsync() 
    { 
     await _entities.SaveChangesAsync(); 
    } 

    public void Dispose() 
    { 
     if (_entities != null) 
     { 
      _entities.Dispose(); 
      _entities = null; 
      GC.SuppressFinalize(this); 
     } 
    } 
} 
+0

Пожалуйста, добавьте код 'GenericRepository' класса реализации;). –

ответ

0

Я думаю, что у вас есть некоторые наследственные хранилища, как эти:

Public Repository1<Class1, KeyClass1> : GenericRepository<T, TEntityKey> 
{ 
    Public Repository1(IDbContext c) : base(c) { } 
} 

Public Repository2<Class2, KeyClass2> : GenericRepository<T, TEntityKey> 
{ 
    Public Repository2(IDbContext c) : base(c) { } 
} 

Это означает, что ваш замок Виндзор будет создать один экземпляр для IDbContext и впрыскивает его в обоих хранилища, что вызывает ваша ошибка.

Я могу предложить вам изменить базовый класс на это:

public abstract class GenericRepository<T, TEntityKey> : IGenericRepository<T, TEntityKey> 
    where T : EntityBase<TEntityKey> 
{ 
    protected IDbContext _entities; 
    protected readonly IDbSet<T> _dbset; 

    protected GenericRepository() 
    { 
     _entities = new MyDbContext(); 
     _dbset = _entities.Set<T>(); 
    } 

    ... 
}