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 实例。