Web API 请求后记录所需的 EF DbContext 的 Castle Windsor Lifestyle
Castle Windsor Lifestyle for EF DbContext Needed For Logging After Web API Request
我正在使用 Castle Windsor 作为 Web 的 DI 容器 API 2 并且我的一些控制器具有 EF DbContext 依赖项,我正在使用以下 CW 安装程序注入它们(这部分工作正常):
public class ApiControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());
}
}
public class MyEntitiesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<MyEntities>().LifestylePerWebRequest());
}
}
我还使用以下消息处理程序进行了全局日志记录:
public class LoggingHandler : DelegatingHandler
{
private readonly IWindsorContainer _container;
public LoggingHandler(IWindsorContainer container)
{
_container = container;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Logic here to parse the request, send off the request, and then parse the response for logging info
// Log to database
using (MyEntities myEntities = _container.Resolve<MyEntities>())
{
// Log to database using MyEntities (DbContext)
}
return response;
}
}
... 像这样在 WebApiConfig.cs 中设置:
public static void Register(HttpConfiguration config, IWindsorContainer container)
{
// Unrelated code
config.MessageHandlers.Add(new LoggingHandler(container));
}
问题是我在尝试访问 MyEntities
(扩展 EF DbContext
)时在 LoggingHandler
中遇到异常,因为它说它已被处置。我认为发生这种情况是因为 MyEntitiesInstaller
将其注册为 LifestylePerWebRequest()
并且此时请求已经完成。我不认为全局更改 DbContext
的生活方式是个好主意,因为出于 api 控制器的目的,我们确实希望它成为每个 Web 请求的一个实例。但是如何防止它在日志记录发生之前被处理(或者更好的是,使用单独的实例进行日志记录)?
感谢@emodendroket 的评论为我指明了正确的方向。我能够通过在 Web 请求之外为我需要的 DbContext 使用不同的命名实例,使用短暂的生活方式(并在使用后立即手动处理)来实现这一点。
安装人员:
public class MyEntitiesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<MyEntities>().LifestylePerWebRequest().IsDefault(),
Component.For<MyEntities>().Named("MyEntitiesTransient").LifestyleTransient());
}
}
日志处理程序的用法:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Logic here to parse the request, send off the request, and then parse the response for logging info
// Log to database
using (MyEntities myEntities = _container.Resolve<MyEntities>("MyEntitiesTransient"))
{
// Log to database using MyEntities (DbContext)
_container.Release(myEntities);
}
return response;
}
控制器继续使用具有 per-web-request 生活方式的 unnamed/default 实例。
我正在使用 Castle Windsor 作为 Web 的 DI 容器 API 2 并且我的一些控制器具有 EF DbContext 依赖项,我正在使用以下 CW 安装程序注入它们(这部分工作正常):
public class ApiControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());
}
}
public class MyEntitiesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<MyEntities>().LifestylePerWebRequest());
}
}
我还使用以下消息处理程序进行了全局日志记录:
public class LoggingHandler : DelegatingHandler
{
private readonly IWindsorContainer _container;
public LoggingHandler(IWindsorContainer container)
{
_container = container;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Logic here to parse the request, send off the request, and then parse the response for logging info
// Log to database
using (MyEntities myEntities = _container.Resolve<MyEntities>())
{
// Log to database using MyEntities (DbContext)
}
return response;
}
}
... 像这样在 WebApiConfig.cs 中设置:
public static void Register(HttpConfiguration config, IWindsorContainer container)
{
// Unrelated code
config.MessageHandlers.Add(new LoggingHandler(container));
}
问题是我在尝试访问 MyEntities
(扩展 EF DbContext
)时在 LoggingHandler
中遇到异常,因为它说它已被处置。我认为发生这种情况是因为 MyEntitiesInstaller
将其注册为 LifestylePerWebRequest()
并且此时请求已经完成。我不认为全局更改 DbContext
的生活方式是个好主意,因为出于 api 控制器的目的,我们确实希望它成为每个 Web 请求的一个实例。但是如何防止它在日志记录发生之前被处理(或者更好的是,使用单独的实例进行日志记录)?
感谢@emodendroket 的评论为我指明了正确的方向。我能够通过在 Web 请求之外为我需要的 DbContext 使用不同的命名实例,使用短暂的生活方式(并在使用后立即手动处理)来实现这一点。
安装人员:
public class MyEntitiesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<MyEntities>().LifestylePerWebRequest().IsDefault(),
Component.For<MyEntities>().Named("MyEntitiesTransient").LifestyleTransient());
}
}
日志处理程序的用法:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Logic here to parse the request, send off the request, and then parse the response for logging info
// Log to database
using (MyEntities myEntities = _container.Resolve<MyEntities>("MyEntitiesTransient"))
{
// Log to database using MyEntities (DbContext)
_container.Release(myEntities);
}
return response;
}
控制器继续使用具有 per-web-request 生活方式的 unnamed/default 实例。