我在ASP.NET MVC应用程序中具有自托管的WebAPI。我想在执行我的API动作之一时执行一些异步动作。 异步操作具有对DbContext的依赖性以及其他一些依赖性。
以下是我的简单喷射器配置。
public class SimpleInjectorIntegrator
{
private static Container container;
public static Container Setup()
{
container = new Container();
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
defaultLifestyle: new WebRequestLifestyle(),
fallbackLifestyle: new AsyncScopedLifestyle());
container.Register<IBaseRepository<User>, BaseRepository<User>>(Lifestyle.Scoped);
container.Register<ComputationService>(Lifestyle.Scoped);
container.Register<ILog, Logger>(Lifestyle.Scoped);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
}
public static T Get<T>() where T : class
{
if (container == null)
throw new InvalidOperationException("Container hasn't been initialized.");
return container.GetInstance<T>();
}
}
Global.asax.cs看起来像这样。
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
var container = SimpleInjectorIntegrator.Setup();
GlobalConfiguration.Configure(WebApiConfig.Register);
...some other code...
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
}
下面是API控制器。
public class ExperimentUploadController : ApiController
{
private ComputationService _service = SimpleInjectorIntegrator.Get<ComputationService>();
public IHttpActionResult Started(InputModel model)
{
...Do Something...
var task = Task.Run(() =>
{
_service.Do(model.Id);
});
}
}
API取决于ComputationService
,该API使用存储库执行与数据库的连接。当我尝试从ComputationService
访问数据库时,它抛出了DbContext被丢弃的情况。
ComputationService
代码如下:
public class ComputationService
{
private IBaseRepository<User> _userRepo = SimpleInjectorIntegrator.Get<User>();
public void Do(int id)
{
///throws here
var user = _userRepo.Get(id);
}
}
我不确定为什么会这样。
答案 0 :(得分:0)
我面临的实际问题是我不希望我的API等待异步操作完成,因此像@John所提到的那样处理DbContext。但是我需要使用SimpleInjector来使用AsyncScopedLifestyle来解决依赖关系,因为我已经在配置中对其进行了配置。
我使用此Github link找到了答案。我所做的是将我的Asynchronous方法包装在Asynchronous范围内,并解决了该范围内的依赖关系,并且有效。
这是更新的代码。
public class ComputationService
{
private IBaseRepository<User> _userRepo;
public void Do(int id)
{
using(AsyncScopedLifestyle.BeginScope(SimpleInjectorIntegrator.Container))
{
_userRepo = = SimpleInjectorIntegrator.Container.GetInstance<User>();
var user = _userRepo.Get(id); //works fine.
}
}
}
我进行的另一项更改是通过SimpleInjectorIntegrator
类中的Property公开Container。