如何从全局过滤器中的NHibernate会话获取更新的对象

时间:2014-11-23 14:33:57

标签: c# asp.net-mvc nhibernate asp.net-mvc-5

我有以下全局过滤器代码:

public class UserAuthorizationFilter : FilterAttribute, IAuthorizationFilter
{
    private readonly IAdministratorService _administratorService;

    public UserAuthorizationFilter()
    {
        _administratorService = IoCFactory.Container.GetInstance<IAdministratorService>();
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        string username = HttpContext.Current.User.Identity.Name;
        IRequestMessage<string> request = MessageFactory.BuildRequestFor(username, username);
        Administrator administrator = _administratorService.GetDetailByName(request).Data;

        filterContext.Controller.ViewBag.Username = username;
        filterContext.Controller.ViewBag.IsAdmin = administrator != null;

        if (administrator != null)
        {
            bool isManageRole = administrator.Roles.Any(r => r.IsManageRole);
            bool isManageAdministrator = administrator.Roles.Any(r => r.IsManageAdministrator);
            bool isManageReviewer = administrator.Roles.Any(r => r.IsManageReviewer);

            filterContext.Controller.ViewBag.IsManageRole = isManageRole;
            filterContext.Controller.ViewBag.IsManageAdministrator = isManageAdministrator;
            filterContext.Controller.ViewBag.IsManageReviewer = isManageReviewer;

        }
    }
}

我在global.asax的Application_Start事件中添加了这个过滤器:

GlobalFilters.Filters.Add(new UserAuthorizationFilter(), 0);

当我将管理员角色属性(例如IsManageRole)从true更新为false时,数据已成功更新到数据库。但是,在UserAuthorizationFilter管理员对象中的属性角色未更新,其仍然加载true值。我试过调用sessionFactory.Evict(typeof(Role))session.Clear(),但没有找到运气。数据仍然不会加载新更新的Role属性。如果我重新启动Web应用程序,属性已更新。

我该如何解决这个问题?为什么nhibernate缓存不会被上面的函数清楚和更新,有什么建议吗?请帮忙..

1 个答案:

答案 0 :(得分:1)

在这里看一下IAdministratorService的实现会很有意思,它如何缓存 .GetDetailByName(request) 方法调用的结果。

重点是:ASP.NET MVC过滤器可以被视为单例。请参阅:Are ActionFilterAttributes reused across threads? How does that work?

  

...在ASP.NET MVC 3中,过滤器被更积极地缓存。因此,任何不正确地存储实例状态的自定义操作过滤器可能会被破坏......

让我们考虑一下,他们被实例化一次,他们永远活着,没有“重建”。即没有新的IoC / DI通过构造函数。

如何解决这个问题还有更多方法。

我。肮脏的方法是在每个IoCFactory.Container.GetInstance<IAdministratorService>();中拨打 OnAuthorization() 。这应该最有可能返回新的新服务,并在当前会话中访问新数据。它应该起作用......但是:Mark Seemann的Service Locator is an Anti-Pattern

II。请参阅Brad Wilson关于提供filters in MVC的文章,主要是以下部分:向过滤器添加依赖注入。简而言之,使用Unity IoC,每个属性都使用setter注入进行了丰富。请参阅过滤器提供程序的代码段:

var attributes = base.GetActionAttributes(controllerContext,
                                              actionDescriptor);
foreach (var attribute in attributes) {
  _container.BuildUp(attribute.GetType(), attribute);
}

III。我会选择一些由提供者模式表示的共享“应用程序缓存”。 (尽管有Mar​​k Seemann的Provider is not a pattern

  • 过滤器将与某些SecurityManager进行通信。
  • 会有一些单身SecurityProvider,从当前会话中获取新数据并缓存它们。
  • 缓存将在一段合理的时间后被清除(我说安全分钟)
  • “安全”对象上的事件系统也会触发cache.Clear()
  • AOP Mvc过滤器可以访问最新的安全数据