问题
I'm trying to use my UnitOfWork inside an implementation of IAuthorizationFilter
, but after I navigate between a few pages I get this exception:
System.InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.
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...
}
}
I was able to get around this with:
// NinjectMappings
Bind<IUnitOfWork>()
.ToMethod(m => GetUnitOfWork())
.WhenInjectedExactlyInto(typeof(PermissionFilter));
private IUnitOfWork GetUnitOfWork()
{
return new UnitOfWork(new MyContext());
}
The problem now is that GetUnitOfWork
is only called once, at app start. I tried alternating between InTransientScope
and InRequestScope
to no avail. So updates to the database are not retrieved, instead my UnitOfWork always returns the same data.
I have read quite a few questions dealing with DbContext has been disposed
but none of them were implementing an IAuthorizationFilter
.
What is the best way to solve this? I'd like to avoid new
or using()
inside the filter or using the Service Locator pattern.
回答1:
Your problem comes from the fact that your MyContext is instantiated in the scope of a request and is disposed at the end of the request.
To solve this avoiding new()
, using
, or ServiceLocator pattern, you may rely on a dedicated 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;
}
}
Your bindings would then be :
public class NinjectMappings : NinjectModule
{
public override void Load()
{
Bind<MyContext>().ToSelf().InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>();
Bind<IFilterProvider>().To<PermissionFilterProvider>();
Bind<PermissionFilter>().ToSelf();
}
}
Note that you will need an Ninject Factory extension like Ninject.Extensions.Factory to achieve the Func<PermissionFilter>
factory pattern in PermissionFilterProvider
constructor.
Also, I am not sure of the scope of your IUnitOfWork
. Shouldn't it be the same as your MyContext
?
来源:https://stackoverflow.com/questions/35122561/using-iauthorizationfilter-with-ninject-and-ef-gives-dbcontext-has-been-disposed