使用IAuthorizationFilter和Ninject和EF给DbContext配置了错误

时间:2016-02-01 03:23:25

标签: c# asp.net-mvc entity-framework ninject

我正在尝试在IAuthorizationFilter的实现中使用我的UnitOfWork,但在我在几个页面之间导航后,我得到了这个例外:

  

System.InvalidOperationException:无法完成操作,因为DbContext已被释放。

FilterConfig.cs

filters.Add(DependencyResolver.Current.GetService(typeof(PermissionFilter)));

NinjectMappings.cs

public class NinjectMappings : NinjectModule
{
    public override void Load()
    {
        Bind<MyContext>().ToSelf().InRequestScope();
        Bind<IUnitOfWork>().To<UnitOfWork>();
    }
}

PermissionFilter.cs

public class PermissionFilter : IAuthorizationFilter
{
    public PermissionFilter(IUnitOfWork unitOfWork)
    {
        // etc...
    }
}

我能够解决这个问题:

// NinjectMappings
Bind<IUnitOfWork>()
    .ToMethod(m => GetUnitOfWork())
    .WhenInjectedExactlyInto(typeof(PermissionFilter));

private IUnitOfWork GetUnitOfWork()
{
    return new UnitOfWork(new MyContext());
}

现在的问题是{app}启动时只调用GetUnitOfWork一次。我尝试在InTransientScopeInRequestScope之间交替无效。因此,不会检索数据库的更新,而是我的UnitOfWork始终返回相同的数据。

我已经阅读了很多关于DbContext has been disposed的问题,但没有一个问题正在实施IAuthorizationFilter

解决此问题的最佳方法是什么?我想避免使用过滤器内的newusing()或使用服务定位器模式。

1 个答案:

答案 0 :(得分:1)

您的问题来自于您的MyContext在请求范围内实例化并在请求结束时处理。

要解决此问题,避免使用new()using或ServiceLocator模式,您可以依赖专用的IFilterProvider

public class PermissionFilterProvider : IFilterProvider
{
    private readonly Func<PermissionFilter> _permissionFilterFactory = null;

    public PermissionFilterProvider(Func<PermissionFilter> filterFactory)
    {
        _permissionFilterFactory = filterFactory;
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var filters = new List<Filter>(); 

        // instantiate PermissionFilter action filter  
        filters.Add(new Filter(_permissionFilterFactory(), FilterScope.Action, 0));
        return filters;
    }
}

您的绑定将是:

public class NinjectMappings : NinjectModule
{
    public override void Load()
    {
        Bind<MyContext>().ToSelf().InRequestScope();
        Bind<IUnitOfWork>().To<UnitOfWork>();
        Bind<IFilterProvider>().To<PermissionFilterProvider>();
        Bind<PermissionFilter>().ToSelf();
    }
}

请注意,您需要像Ninject.Extensions.Factory这样的Ninject Factory扩展来在Func<PermissionFilter>构造函数中实现PermissionFilterProvider工厂模式。

另外,我不确定IUnitOfWork的范围。不应该与您的MyContext相同吗?