一起使用NHibernate拦截与Ninject来获取登录的用户(Using NHibernate

2019-10-19 02:37发布

我正在读这篇文章 ,发现它很有趣(感谢@Aaronaught)。 是什么最接近于解决我的问题。

唯一的细节是,在我的情况我会使用NHibernate的拦截器,但会抛出异常An unhandled exception of type 'System.StackOverflowException' occurred in System.Core.dll

会话工厂:

public class SessionFactoryBuilder : IProvider
{
    private ISessionFactory _sessionFactory;
    private readonly Configuration _configuration;

    public SessionFactoryBuilder(AuditInterceptor auditInterceptor)
    {
        _configuration = Fluently.Configure(new Configuration().Configure())
                .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<IEntidade>(new AutomappingConfiguration())))
                .ExposeConfiguration(SetupDatabase)
                .BuildConfiguration();

        _configuration.SetInterceptor(auditInterceptor);

        _sessionFactory = _configuration.BuildSessionFactory();
    }

    private static void SetupDatabase(Configuration config)
    {
        var schema = new SchemaExport(config);
        //schema.Execute(true, true, false);
    }

    public object Create(IContext context)
    {
        return _sessionFactory;
    }

    public Type Type
    {
        get { return typeof(ISessionFactory); }
    }
}

我有设置我的资料库和ORM模块(NHibernate的)

public class RepositoriosModule : NinjectModule
{
    public override void Load()
    {
        Bind<AuditInterceptor>().ToSelf().InRequestScope();

        // NHibernate 
        Bind<ISessionFactory>().ToProvider<SessionFactoryBuilder>().InSingletonScope();
        Bind<ISession>().ToMethod(CreateSession).InRequestScope();
        Bind<NHUnitOfWork>().ToSelf().InRequestScope();

        //Model Repositories
        Bind<IRepositorio<Usuario>, IUsuariosRepositorio>().To<UsuariosRepositorio>().InRequestScope();
    }

    private ISession CreateSession(IContext context)
    {
        return context.Kernel.Get<ISessionFactory>().OpenSession();
    }
}

拦截器来更新可审计的性质( CriadoEm (在创建), CriadoPor (创建由) AtualizadoEmAtualizadoPor

public class AuditInterceptor : EmptyInterceptor
{
    private readonly IUsuario _usuarioLogado;
    public AuditInterceptor(IUsuario usuarioLogado)
    {
        _usuarioLogado = usuarioLogado;
    }

    public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
    {
        var auditableObject = entity as IAuditavel;
        if (auditableObject != null)
        {
            currentState[Array.IndexOf(propertyNames, "AtualizadoEm")] = DateTime.Now;
            return true;
        }
        return false;
    }

    public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
    {
        var auditableObject = entity as IAuditavel;
        if (auditableObject != null)
        {
            var currentDate = DateTime.Now;
            state[Array.IndexOf(propertyNames, "CriadoEm")] = currentDate;
            return true;
        }
        return false;
    }
}

提供者以获取登录的用户:

公共类UsuarioProvider:供应商{私人用户_usuario;

protected override Usuario CreateInstance(IContext context)
{
    var usuariosRepositorio = context.Kernel.Get<IUsuariosRepositorio>(); // Stackoverflow on this line!!

    if (_usuario == null && WebSecurity.IsAuthenticated)
        _usuario = usuariosRepositorio.Get(WebSecurity.CurrentUserId);
    return _usuario;
}

}

和类NinjectWebCommon (Web应用程序)定义:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IUsuario>().ToProvider<UsuarioProvider>().InRequestScope(); //.When((req) => WebSecurity.IsAuthenticated)
    kernel.Load(new RepositoriosModule(), new MvcSiteMapProviderModule());
}

[添加] repository类

public class UsuariosRepositorio : Repositorio<Usuario>, IUsuariosRepositorio
{
    public UsuariosRepositorio(NHUnitOfWork unitOfWork)
        : base(unitOfWork)
    { }
}


public class Repositorio<T> :  IRepositorio<T>
    where T : class, IEntidade
{

    private readonly NHUnitOfWork _unitOfWork;
    public IUnitOfWork UnitOfWork { get { return _unitOfWork; } }
    private readonly ISession _session;

    public Repositorio(IUnitOfWork unitOfWork)
    {
        _unitOfWork = (NHUnitOfWork)unitOfWork;
        _session = _unitOfWork.Context.SessionFactory.GetCurrentSession();
    }

    public void Remover(T obj)
    {
        _session.Delete(obj);
    }

    public void Armazenar(T obj)
    {
        _session.SaveOrUpdate(obj);
    }

    public IQueryable<T> All()
    {
        return _session.Query<T>();
    }

    public object Get(Type entity, int id)
    {
        return _session.Get(entity, id);
    }

    public T Get(Expression<Func<T, bool>> expression)
    {
        return Query(expression).SingleOrDefault();
    }

    public T Get(int id)
    {
        return _session.Get<T>(id);
    }

    public IQueryable<T> Query(Expression<Func<T, bool>> expression)
    {
        return All().Where(expression);
    }
}

问题

发生在类的问题UsuarioProvider试图获取用户信息库。

计算器错误:

An unhandled exception of type 'System.StackOverflowException' occurred in System.Core.dll

Answer 1:

我看到两个问题:

我看到的主要问题是, SessionFactoryBuilder需要一个AuditInterceptor这需要一个IUsuario ,这需要一个UsuarioProvider ,这需要一个SessionFactoryBuilder ,从而引入一个周期,和一个堆栈上溢。

我看到的第二个问题是,你的AuditInterceptor链接到一个请求时,你SessionFactoryBuilder是单身等等。 我必须承认,我看不出它如何与几个登录的用户。

您应该实例,并附加AuditInterceptor作为的一部分CreateSession ,而不是试图一劳永逸的会话生成器的一部分,创建它。 一旦做到这一点,你的拦截器不应该依赖于需要的AuditInterceptor作为其创作的一部分的会话(你可能需要一个单独的会话创建机制为一种无状态的会话可能做的伎俩)



文章来源: Using NHibernate interceptor together with Ninject to retrieve the logged in user