使用NHibernate拦截器和Ninject检索登录用户

使用NHibernate拦截器和Ninject检索登录用户,nhibernate,fluent-nhibernate,ninject,asp.net-mvc-5,Nhibernate,Fluent Nhibernate,Ninject,Asp.net Mvc 5,我正在阅读,发现它很有趣(谢谢@Aaronaught)。是最能解决我问题的方法 唯一的细节是,在我的例子中,我将使用NHibernate拦截器,但是抛出了一个异常System.Core.dll中发生了一个类型为“System.StackOverflowException”的未处理异常 代码 会话工厂: public class SessionFactoryBuilder : IProvider { private ISessionFactory _sessionFactory;

我正在阅读,发现它很有趣(谢谢@Aaronaught)。是最能解决我问题的方法

唯一的细节是,在我的例子中,我将使用NHibernate拦截器,但是抛出了一个异常
System.Core.dll中发生了一个类型为“System.StackOverflowException”的未处理异常

代码 会话工厂:

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); }
    }
}
检索登录用户的提供程序:

公共类提供程序:提供程序 { 私人乌萨里奥(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;
}
[添加]存储库类
public class usariosrepositorio:Repositorio,IUsuariosRepositorio
{
公共用益准备金(NHUnitOfWork unitOfWork)
:基础(工作单元)
{ }
}
公共类存储:IRepositorio
其中T:class,IEntidade
{
私有只读NHUnitOfWork _unitOfWork;
公共IUnitOfWork UnitOfWork{get{return{U UnitOfWork;}}
专用只读会话;
公共仓库(IUnitOfWork unitOfWork)
{
_unitOfWork=(NHUnitOfWork)unitOfWork;
_session=_unitOfWork.Context.SessionFactory.GetCurrentSession();
}
公共空隙清除器(T obj)
{
_删除(obj);
}
Armazenar公共空间(T obj)
{
_会话。保存或更新(obj);
}
公共IQueryable All()
{
返回_session.Query();
}
公共对象Get(类型实体,int-id)
{
return _session.Get(实体,id);
}
公共T获取(表达式)
{
返回查询(表达式).SingleOrDefault();
}
公共T获取(int id)
{
return _session.Get(id);
}
公共IQueryable查询(表达式)
{
返回All(),其中(表达式);
}
}
问题 在尝试检索用户存储库时,类
UsuarioProvider
中出现问题

堆栈溢出错误:

System.Core.dll中发生“System.StackOverflowException”类型的未处理异常

我看到两个问题:

我看到的主要问题是,
SessionFactoryBuilder
需要一个
AuditInterceptor
,它需要一个
IUsuario
,它需要一个
UsuarioProvider
,它需要一个
SessionFactoryBuilder
,从而引入循环和堆栈溢出

我看到的第二个问题是,当您的
SessionFactoryBuilder
类似于单例时,您的
试听器链接到一个请求。我必须承认,我看不出它如何与几个登录用户一起工作


您应该实例化并附加
AuditInterceptor
,作为
CreateSession
的一部分,而不是尝试作为会话生成器的一部分一次性创建它。一旦完成,您的拦截器就不应该依赖需要AuditInterceptor作为其创建一部分的会话(为此,您可能需要一个单独的会话创建机制。无状态会话可能会起到作用)

你能发布类的代码吗?
通常是repositorio
?Hi@jbl我编辑了这个问题。.lookDebugging应该会直接导致这个问题。你的大多数TL可能有一个循环依赖关系,如果你看一下堆栈跟踪和参数,你就会知道是什么导致了循环依赖关系。@Ridermansb顺便说一句,你似乎没有使用它您的
IUsuario usuarioLogado
在您的试听器中,您需要它做什么?另外,您可能只需要用户id,它是
WebSecurity。CurrentUserId
已经提供,无需查询数据库
IUsuarioLogado'
我稍后将使用它来设置属性(谁创建/修改了记录),这只是一个关于UserId agree的演示。但由于我使用ORM NHibernate,而且在其他情况下我也需要该属性,所以我甚至没有弄清楚如何放置这些字段。因此,我们的想法是让
CreateBy
(对象)和
CreateById
如何配置每个会话的IAuditInterceptor?@Ridermansb拦截器只需实例化并作为参数传递给OpenSession方法
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;
    }
}
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;
}
private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IUsuario>().ToProvider<UsuarioProvider>().InRequestScope(); //.When((req) => WebSecurity.IsAuthenticated)
    kernel.Load(new RepositoriosModule(), new MvcSiteMapProviderModule());
}
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);
    }
}