每个请求

时间:2015-10-28 11:38:10

标签: c# entity-framework async-await asp.net-web-api2 unity-container

在我开始在过滤器中使用DI后,我得到了下一个EF异常:

  

在上一次异步操作完成之前,在此上下文中启动了第二个操作。使用'等待'确保在调用此上下文中的另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

我使用Unity作为我的IoC容器。我的设置如下:

config.DependencyResolver = new UnityHierarchicalDependencyResolver(container);

var providers = GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();

//adding IFilterProvider provided by Unity
GlobalConfiguration.Configuration.Services.Add(
    typeof(IFilterProvider),
    new UnityActionFilterProvider(UnityConfig.GetConfiguredContainer()));

var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);

//removing default IFilterProvider
GlobalConfiguration.Configuration.Services.Remove(
    typeof(IFilterProvider),
    defaultprovider);

然后我按照以下方式注册我的过滤器进行授权:

var authFilter = config.DependencyResolver.GetService(typeof(MyFilterType));
config.Filters.Add((MyFilterType)authFilter);

我的授权过滤器如下所示:

public class MyFilterType : IAuthorizationFilter
{
    private readonly MyServiceInterfaceType _service;

    public MyFilterType(MyServiceInterfaceType service)
    {
        _service = service;
    }

    public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext,
        CancellationToken cancellationToken,
        Func<Task<HttpResponseMessage>> continuation)
    {
        var res = await _service.SomeAction();

        //the rest doesn't matter
    }
}

MyServiceInterfaceType内部聚合MyRepositoryInterfaceType。所以它只是通常的Service-Repository模式。 内部MyRepositoryInterfaceType EF上下文已初始化。

所以,关于例外。我知道这意味着什么 - 有对上下文的并发异步调用。我认为这是因为这两行:

var authFilter = config.DependencyResolver.GetService(typeof(MyFilterType));
config.Filters.Add((MyFilterType)authFilter);

过滤器实例基本上存储在单例中。因此,每个过滤器调用都由相同的EF上下文实例提供,这就是存在异常的原因。

(如果我错了,请纠正我。)

我的问题是: 是否可以为每次调用创建我的MyFilterType过滤器的实例以避免这些异常?

1 个答案:

答案 0 :(得分:1)

您需要在方法内部进行服务定位。

var requestScope = actionContext.Request.GetDependencyScope();
var myService = requestScope.GetService(MyServiceInterfaceType) as MyServiceInterfaceType;

Autofac有自己的过滤器,如果你使用它而不是Unity,你可以使用它,但我不认为Unity提供类似的东西。 Autofac文档提供了很好的解释: http://docs.autofac.org/en/latest/integration/webapi.html#provide-filters-via-dependency-injection