Reputation: 114
I have included Coravel scheduler in my ASP.NET application.
Everything seems to work well, but when the scheduler starts running it returns System.ObjectDisposedException on the DataContext. I use Dependency Injection in my repository classes, does the context only get created when it receives a request from the browser? How can I fix this so the context is available when my scheduler runs the method?
Below is my repository code
using System.Collections.Generic;
using System.Threading.Tasks;
using Project.Models;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace Project.Data.CustomerRepo
{
public class CustomerRepository : ICustomerRepository
{
private readonly DataContext _context;
public CustomerRepository(DataContext context)
{
this._context = context;
}
public async Task<Customer> Create(Customer customer)
{
await _context.Customers.AddAsync(customer);
return customer;
}
public async Task<IEnumerable<Customer>> Create(IEnumerable<Customer> customers)
{
await _context.Customers.AddRangeAsync(customers);
await _context.SaveChangesAsync();
return customers;
}
public async Task Delete(Customer customer)
{
_context.Customers.Remove(customer);
await _context.SaveChangesAsync();
}
public async Task<Customer> Read(int id)
{
var customer = await _context.Customers.FirstOrDefaultAsync(customerItem => customerItem.Id == id);
return customer;
}
public async Task<Customer> ReadFromFacebookId(string id)
{
var customer = await _context.Customers.Where(customerItem => customerItem.FacebookId == id).FirstOrDefaultAsync();
return customer;
}
public async Task<IEnumerable<Customer>> Read()
{
var customers = await _context.Customers.ToListAsync();
return customers;
}
public async Task<Customer> Update(Customer customer)
{
_context.Update(customer);
await _context.SaveChangesAsync();
return customer;
}
}
}
Upvotes: 1
Views: 1827
Reputation: 20126
services.AddDbContext<>()
registers the DataContext
as a service with ServiceLifetime.Scoped
which means that your DataContext
is created per web request. It is disposed when request is completed.
You could inject IServiceScopeFactory
which is singleton into your controller/repository, then create a new scope using CreateScope()
and request the DataContext
service from that scope
public class CustomerRepository : ICustomerRepository
{
IServiceScopeFactory _serviceScopeFactory
public CustomerRepository(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public async Task<Customer> Create(Customer customer)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<DataContext>();
await context.Customers.AddAsync(customer);
return customer;
}
return customer;
}
}
Refer to Access DbContext service from background task
Upvotes: 4