ASP.NET WebApi2, контроллер
public class BooksController : ApiController
{
public IRepository Repository
{ get; set; }
public BooksController(IRepository r)
{
Repository = r;
}
...
}
Репозиторий:
public class BookRepository : IRepository, IDisposable
{
public BookContext Context
{ get; set; }
...
protected void Dispose(bool disposing)
{
if (disposing)
{
if (Context != null)
{
Context.Dispose();
Context = null;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Контекст данных:
public class BookContext : DbContext
{
public DbSet<Book> Books
{ get; set; }
}
В качестве IoC используется Autofac, контейнер конфигурируется в Global.asax:
protected void Application_Start()
{
AutofacConfig.ConfigureContainer();
. . .
}
public class AutofacConfig
{
public static void ConfigureContainer()
{
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterType<BookRepository>().InstancePerRequest().As<IRepository>().WithProperty("Context", new BookContext());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
Почему-то при такой регистрации типа BookRepository
не создается новый экземпляр его свойства Context
с новым http-запросом. То есть первый http-запрос в API работает, а на второй возвращается такая ошибка: The operation cannot be completed because the DbContext has been disposed.
Для начала, я бы вам посоветовал переписать ваш репозиторий. В нем мне не нравится 2 вещи:
Инъекция в свойство. По моему мнению, если класс имеет обязательные зависимости, то они должны быть отражены в конструкторе. Иначе остается возможность создать класс и не инициализировать свойство, без которого класс не работает.
Второе, что мне не нравится - это ваша реализация IDisposable
. Зачем вам делить её на 2 функции? Вы планируете в наследниках добавлять финализатор? Я так не думаю. Я бы вообще наследование от этого класса запретил.
В итоге, после моих правок, репозиторий станет выглядеть как то так:
public sealed class BookRepository : IRepository, IDisposable
{
public BookRepository(BookContext ctx)
{
_context = ctx;
}
private BookContext _context;
public void Dispose()
{
_context?.Dispose();
_context = null;
}
}
Далее, вы регистрируете ваш репозиторий и указываете для контекста конкретное значение, которое будет использовано для всех репозиториев. Потому у вас при первом запросе контекст уничтожается при последующем уже не работает. Я не спец по autofac, но я бы зарегистрировал сначала контекст в контейнере, а потом репозиторий. Что то типа этого:
builder.RegisterType<BookContext>();
builder.RegisterType<BookRepository>().InstancePerRequest().As<IRepository>();
Никаких инъекций в свойство не надо, зависимость от контекста объявлена в конструкторе репозитория и должна подхватываться контейнером автоматом.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Столкнулся с такой проблемой: Есть космический корабль, у него есть дочерние объекты - орудия на нужных позицияхНо пули спавнятся не там где...
Есть 2 ViewModel`и AuthViewModel и LoginViewModelВ LoginView есть Frame который контент которого LoginControl а у него контекст AuthViewModel
Хочу нарисовать Землю и Луну с использованием своего алгоритма вращения (те