При использовании метода 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();
НИКОГДА не совершайте наш DbContext при утилизации. Dispose вызывается в случае исключения, но вы не хотите сохранять какие-либо изменения, когда это произойдет. – Steven
@Steven: я удалил эту строку, так или иначе это не решит проблему. – user1260827
Каждый раз, когда я видел SaveChanges внутри утилиты, у кодера возникали проблемы. Я еще не понял, какой шаблон дизайна он предлагает или рекомендует «совершает» или «сохраняет» в Dispose. Я собираюсь предложить вам переоценить план, чтобы сохранить его внутри. Как насчет обработки ошибок. почему вы связываете «коммиты» с изменениями в базе данных с сборкой мусора? Стоит прочитать http://msdn.microsoft.com/en-us/library/fs2xkftw%28VS.80%29.aspx Когда вы запускаете утилиту? возможно, начинайте здесь: http://stackoverflow.com/questions/898828/c-sharp-finalize-dispose-pattern –