Согласно документам, когда я настраиваю DbContext, как показано ниже, я регистрирую его в области действия (для каждого HTTP-запроса)
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<DBData>(options => {
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
}
);
Проблема возникает, когда я пытаюсь получить к ней доступ в другом потоке.
public class HomeController : Controller
{
private readonly DBData _context;
public HomeController(DBData context)
{
_context = context;
}
public IActionResult StartInBackground()
{
Task.Run(() =>
{
Thread.Sleep(3000);
//System.ObjectDisposedException here
var res = _context.Users.FirstOrDefault(x => x.Id == 1);
});
return View();
}
}
Я хочу настроить создание DbContext для каждого вызова (AddTransition). Это дало бы мне возможность написать следующий код
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<DBData>(options => {
//somehow configure it to use AddTransient
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
}
);
services.AddTransient<IUnitOfWorkFactoryPerCall, UnitOfWorkFactory>();
services.AddScoped<IUnitOfWorkFactoryPerRequest, UnitOfWorkFactory>();
services.AddMvc();
}
public interface IUnitOfWorkFactoryPerCall : IUnitOfWorkFactory { }
public interface IUnitOfWorkFactoryPerRequest : IUnitOfWorkFactory { }
public interface IUnitOfWorkFactory : IDisposable
{
DBData Context { get; }
}
public class UnitOfWorkFactory : IUnitOfWorkFactoryPerCall, IUnitOfWorkFactoryPerRequest
{
public UnitOfWorkFactory(DBData context)
{
Context = context;
}
public DBData Context
{
get; private set;
}
public void Dispose()
{
Context.Dispose();
}
}
Так что теперь, если я хочу создать DBContext для каждого запроса, я буду использовать IUnitOfWorkFactoryPerRequest, а когда я хочу использовать DBContext в каком-то фоновом потоке, я могу использовать IUnitOfWorkFactoryPerCall.