NHibernate会话自定义数据

时间:2012-07-18 04:26:20

标签: nhibernate

我想要做的是在我为NHibernate配置的Save,Update,Delete监听器中拥有当前用户ID。

在我看来,最好的方法是在ISession对象中插入此信息,并在侦听器中读取此信息。但似乎没有任何地方可以做到。

一种方法是实现接口,但是,我找不到任何可以继承的示例或基类(ISession有太多成员)。一旦我完成实现,我知道听众可以进行类型转换并获得用户ID。

该应用程序是带有Sql Server 2008的ASPNET MVC2。

3 个答案:

答案 0 :(得分:1)

如果您为每个线程使用一个会话,则可以将其存储在线程静态字段中:

[ThreadStatic]
private static int userId;

public static void UserId { get { return userId; } set { userId = value; } }

为避免线程池将值从一个会话传送到另一个会话,您应该在事务结束时重置该值(例如,在事务提交事件中)。

注意:我这样做非常成功。但我把它包裹在一些服务之后。只有一个ThreadStatic字段,它包含一个自制的TransactionContext,它包含会话和我需要的所有其他数据。


当您使用自己的方法访问会话时,可以使用SessionContext类。它需要更改调用者,但您不必包装会话。

这样的事情:

public class ISessionContext : IDisposable
{
  public ISession Session { get; }

  public SessionData Data { get; }
}

public ISessionContext CreateSession()
{
  return new SessionContext(SessionFactory.OpenSession(), new SessionData(user));
}

答案 1 :(得分:0)

我想,我想得更好。

我刚创建了一个实现NHibernate.ISession的包装器,所以在我的方法中:

public NHibernate.ISession OpenDataSession(int userId)
{
  return new SessionWrapper(SessionFactory.OpenSession(), userId, this);
}

这种方式在我的监听器中,我只是输入到SessionWrapper并获取UserId属性。

到目前为止它工作得很好,我的包装器也实现了IDisposable,所以应该没问题。

如果有人知道更好,请告诉我。

更新:根据要求提供更多见解。

SessionWrapper类定义:只需实现NHibernate.ISession并将所有方法重新映射到wrappedSession(构造函数的第一个参数),如:

    public DataStoreSessionWrapper(NHibernate.ISession wrappedSession, UserSession currentUser)
    {
    }

    public NHibernate.EntityMode ActiveEntityMode
    {
      get { return WrappedSession.ActiveEntityMode; }
    }

    public NHibernate.ITransaction BeginTransaction(System.Data.IsolationLevel isolationLevel)
    {
      return WrappedSession.BeginTransaction(isolationLevel);
    }

这个想法是,通过使用Ninject,你可以将NHibernate.ISession绑定到这个包装器。虽然这假定UserSession对象也可以被容器访问,这是真的,因为UserSession可以存储在Session包中。

更新2(因为我正在发展:D):我有另一种方法可以做到这一点,我认为更好。

我没有一个包装器,而是一个接口IUserSessionStore,它基本上只有一个方法:GetUserSession()返回UserSession对象。此接口位于需要此信息的所有类的构造函数中。

通过Ninject,我只需将此接口映射到名为UserSessionStore_ASPNETSession的类,该类通过将对象存储到ASPNET会话包中来实现此目的。

显然我假设这是一个网站,其中所有内容都在一个层中(没有远程处理,或涉及wcf)。

我相信这样做更清洁,速度更快,并且它也有利于所有其他需要此信息的图层。

谢谢!

答案 2 :(得分:0)

我遇到了同样的问题,但我的情况有所不同:

我有NHibernateSessionManager来处理ISessionITransaction等等

然后我在CallContext.SetData中使用NHibernateSessionManager来保存编辑器实体,然后我使用CallContext.GetDataIPreUpdateEventListenerIPreInsertEventListener,{IPreDeleteEventListener中对其进行检索{1}}

CallContext文档:

http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.callcontext.aspx

在网络环境中我使用HttpContext.Current.Items