Ответ 1
При использовании метода WithParameter экземпляр параметра будет одинаковым для каждого разрешенного объекта. Таким образом, при .WithParameter("context", new PcpContext())
вы эффективно используете один и тот же экземпляр класса PcpContext для любого разрешенного экземпляра IRepository.
С вашим текущим кодом, когда экземпляр IRepository размещен, он также удалит экземпляр PcpContext. Тогда любая последующая попытка разрешить IRepository получит экземпляр PcpContext, который был удален. Вам нужен способ получить новый новый экземпляр EF DbContext для каждого запроса Http, который удаляется в конце запроса.
Один из вариантов может состоять в том, чтобы зарегистрировать блок кода для IRepository, чтобы блок кода выполнялся каждый раз, когда IRepository необходимо разрешить:
_builder.Register<IRepository>(c => new EfRepository(new PcpContext()))
Лучшим вариантом было бы создать новую абстракцию IDatabaseContext
, обновив EfRepository
, поэтому она зависит от новой абстракции IDatabaseContext вместо класса PcpContext
(что уже может быть в случае:)).
Класс реализации для IDatabaseContext будет вашим классом PcpContext, который должен наследоваться от EF DbContext и, вероятно, получит строку подключения в качестве параметра.
public class EfRepository : IRepository
{
private readonly IDatabaseContext _context;
public EfRepository(IDatabaseContext context)
{
_context = context;
}
...methods for add, delete, update entities
//There is no longer need for this to be disposable.
//The disaposable object is the database context, and Autofac will take care of it
//public void Dispose()
}
public interface IDatabaseContext : IDisposable
{
... declare methods for add, delete, update entities
}
public class PcpContext: DbContext, IDatabaseContext
{
public EntityFrameworkContext(string connectionString)
: base(connectionString)
{
}
...methods exposing EF for add, delete, update entities
//No need to implement IDisposable as we inherit from DbContext
//that already implements it and we don´t introduce new resources that should be disposed of
}
Это становится лучше с идеей использования контейнера IoC и оставления бремени управления жизненным циклом. Теперь ваш класс репозитория не должен быть одноразовым и не должен управлять и распоряжаться его зависимостью IDatabaseContext. Это Autofac, который будет отслеживать экземпляр контекста и распоряжаться им, когда это необходимо.
По той же причине вы, вероятно, захотите использовать InstancePerLifetimeScope с зависимостью контекста базы данных. Это означало бы, что один и тот же контекст EF используется для каждого экземпляра репозитория в одном и том же запросе Http и размещается в конце запроса.
_builder.RegisterType<EfRepository>()
.As<IRepository>();
_builder.RegisterType<PcpContext>()
.As<IDatabaseContext>()
.WithParameter("connectionString", "NameOfConnStringInWebConfig")
.InstancePerLifetimeScope();