使用NHibernate拦截器和Ninject检索登录用户
我正在阅读,发现它很有趣(谢谢@Aaronaught)。是最能解决我问题的方法 唯一的细节是,在我的例子中,我将使用NHibernate拦截器,但是抛出了一个异常使用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;
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);
}
}