EF 7(核心)。 像AddTransient一样创建DBContext

根据文档,我配置DbContext如下面的DI在范围内注册它(每个http请求)

services.AddEntityFramework() .AddSqlServer() .AddDbContext(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(options => { //somehow configure it to use AddTransient options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]); } ); services.AddTransient(); services.AddScoped(); 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 ,当我想在某些后台线程中使用IUnitOfWorkFactoryPerCall我可以使用IUnitOfWorkFactoryPerCall

我的临时解决方案 我创建了单例,可以“以瞬态方式”创建上下文

 public class AppDependencyResolver { private static AppDependencyResolver _resolver; public static AppDependencyResolver Current { get { if (_resolver == null) throw new Exception("AppDependencyResolver not initialized. You should initialize it in Startup class"); return _resolver; } } public static void Init(IServiceProvider services) { _resolver = new AppDependencyResolver(services); } private readonly IServiceProvider _serviceProvider; public AppDependencyResolver(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IUnitOfWorkFactory CreateUoWinCurrentThread() { var scopeResolver = _serviceProvider.GetRequiredService().CreateScope(); return new UnitOfWorkFactory(scopeResolver.ServiceProvider.GetRequiredService(), scopeResolver); } } 

然后我在Startup Configure方法中调用init方法

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { AppDependencyResolver.Init(app.ApplicationServices); //other configure code } 

毕竟我可以在一些后台线程中调用AppDependencyResolver.Current.CreateUoWinCurrentThread()

如果有人能提供更优雅的解决方案,我将不胜感激。

在你的控制器中,你为什么要尝试注入private readonly DBData _context; ? 如果您已经通过DI注册了IUnitOfWorkFactoryPerCall ,那么您应该将其注入您的控制器吗? 然后,您可以通过界面访问上下文。

为了扩展,我建议你这样做:

 public class HomeController : Controller { private readonly IUnitOfWorkFactoryPerCall _contextFactory; public HomeController(IUnitOfWorkFactoryPerCall contextFactory) { _contextFactory = contextFactory; } public IActionResult StartInBackground() { Task.Run(() => { Thread.Sleep(3000); //System.ObjectDisposedException here var res = _contextFactory.Context.Users.FirstOrDefault(x => x.Id == 1); }); return View(); } }