首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >每个web请求的EF DbContext +自定义RoleProvider =每个web请求或单个实例的RoleProvider?

每个web请求的EF DbContext +自定义RoleProvider =每个web请求或单个实例的RoleProvider?
EN

Stack Overflow用户
提问于 2012-03-22 18:38:42
回答 1查看 2.1K关注 0票数 3

使用封装在接口中的EF DbContext,在每个web请求中注入依赖项,以确保整个请求处理相同的上下文。还有一个定制的RoleProvider,它通过接口使用DbContext来定制授权服务。

到目前为止,我一直在使用服务定位器模式来解决自定义RoleProvider的no-arg构造函数中的RoleProvider实例。这导致了一些小问题,因为RoleProvider是单一的,所以它可能无限期地保留DbContext,而其他请求可能希望在Application_EndRequest期间释放它。

我现在有了一个解决方案基于此,尽管它使用的是与温莎不同的ioc容器。我可以使用DI为每个http请求新建一个自定义RoleProvider实例。

我的问题是,我应该吗?

让一个开放的DbContext挂在RoleProvider上似乎很浪费。另一方面,我知道每个MVC AuthorizeAttribute都会访问RoleProvider (如果它有一个非空的Roles属性,我们大多数人都这样做),所以我认为在等待时已经有一个DbContext可能是有用的。

另一种方法是为RoleProvider注入一个不同的RoleProvider,而这不是每个web请求。这样,只为web请求而存在的DbContext可以在结束时被释放,而不会影响到单个的RoleProvider

这两种方法都更好,为什么呢?

在注释后更新

史蒂文,这基本上就是我所做的。唯一的区别是我不依赖于System.Web.Mvc.DependencyResolver。相反,我在自己的项目中基本上有相同的东西,只是命名不同:

代码语言:javascript
复制
public interface IInjectDependencies
{
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

public class DependencyInjector
{
    public static void SetInjector(IInjectDependencies injector)
    {
        // ...
    }

    public static IInjectDependencies Current
    {
        get
        {
           // ...
        }
    }
}

这些类是项目核心API的一部分,在与MVC不同的项目中。这样,其他项目(以及域项目)就不需要依赖System.Web.Mvc来对其DependencyResolver进行编译。

考虑到这个框架,到目前为止,用SimpleInjector替换Unity是无痛的。以下是多用途的单例RoleProvider设置:

代码语言:javascript
复制
public class InjectedRoleProvider : RoleProvider
{
    private static IInjectDependencies Injector 
        { get { return DependencyInjector.Current; } }

    private static RoleProvider Provider 
        { get { return Injector.GetService<RoleProvider>(); } }

    private static T WithProvider<T>(Func<RoleProvider, T> f)
    {
        return f(Provider);
    }

    private static void WithProvider(Action<RoleProvider> f)
    {
        f(Provider);
    }

    public override string[] GetRolesForUser(string username)
    {
        return WithProvider(p => p.GetRolesForUser(username));
    }

    // rest of RoleProvider overrides invoke WithProvider(lambda)
}

Web.config:

代码语言:javascript
复制
<roleManager enabled="true" defaultProvider="InjectedRoleProvider">
    <providers>
        <clear />
        <add name="InjectedRoleProvider" type="MyApp.InjectedRoleProvider" />
    </providers>
</roleManager>

IoC容器:

代码语言:javascript
复制
Container.RegisterPerWebRequest<RoleProvider, CustomRoleProvider>();

至于CUD,只有一个方法在我的CustomRoleProvider中实现。

代码语言:javascript
复制
public override string[] GetRolesForUser(string userName)

这是MVC的AuthorizeAttribute (和IPrincipal.IsInRole)使用的唯一方法,从所有其他方法来看,我只是简单地

代码语言:javascript
复制
throw new NotSupportedException("Only GetRolesForUser is implemented.");

由于在提供程序上没有角色CUD操作,所以我不担心事务。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-23 07:22:53

看看Griffin.MvcContrib项目。它包含一个MembershipProviderRoleProvider实现,该实现利用了MVC DependencyResolver

您可以像这样配置RoleProvider

代码语言:javascript
复制
<roleManager enabled="true" defaultProvider="MvcRoleManager">
  <providers>
    <clear />
    <add name="MvcRoleManager" 
      type="Griffin.MvcContrib.Providers.Roles.RoleProvider, Griffin.MvcContrib"
    />
  </providers>
</roleManager>

它利用了System.Web.MVC DependencyResolver类,因此您需要为正在使用的DI容器配置IDependencyResolver实现。使用简单注入器(和SimpleInjector.MVC3集成NuGet软件包),您需要在Application_Start事件中进行以下配置:

代码语言:javascript
复制
container.RegisterAsMvcDependencyResolver();

Griffin.MvcContrib.Providers.Roles.RoleProvider使用在同一程序集中定义的IRoleRepository的依赖项。现在,您不必实现一个完整的角色提供程序,而只需实现IRoleRepository并在容器中注册它:

代码语言:javascript
复制
container.Register<IRoleRepository, MyOwnRoleRepository>();

您可以在这里的NuGet上找到这个项目。

更新

现在让我们回答这个问题:

Griffin.MvcContrib RoleProvider将是单例的,问题现在转移到IRoleRepository及其依赖项,但问题仍然存在。

如果您所做的只是从角色提供程序中读取(永远不要更新数据库);在这种情况下,您所选择的生命周期并不重要,只要您不在线程上重用相同的DbContext

但是,当您确实使用角色提供程序更新数据库时,情况就不同了。在这种情况下,我会给它自己的上下文,并让它在每次操作之后显式地提交它。因为如果你不这样做,谁会提交这些更改?在命令处理程序(特别是TransactionCommandHandlerDecorator)的上下文中运行时,该操作将在命令成功后提交,并在命令失败时回滚。也许在命令失败时回滚更改是可以的。但是,当角色提供程序在命令处理程序的上下文之外运行时,谁来提交它呢?我相信你能解决这个问题,但我相信你最终会有一个很难掌握的系统,它会让其他开发人员眼花缭乱,他们试图找出为什么这些变化没有发生。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9828448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档