NHibernate-管理SessionFactory/Session的优秀完整工作助手类

NHibernate-管理SessionFactory/Session的优秀完整工作助手类,nhibernate,Nhibernate,任何人都可以提供/引用一个适当的OO类型帮助类来管理SessionFactory的单例,然后再管理会话吗?当然,这是我开始使用NHibernate时使用的: 会话工厂 public class BaseDataAccess { protected ISession m_session; public BaseDataAccess() { m_session = NHibernateHttpModule.CurrentSession; } public stati

任何人都可以提供/引用一个适当的OO类型帮助类来管理SessionFactory的单例,然后再管理会话吗?

当然,这是我开始使用NHibernate时使用的:

会话工厂

public class BaseDataAccess
{

  protected ISession m_session;

  public BaseDataAccess()
  {
    m_session = NHibernateHttpModule.CurrentSession;
  }

  public static ISession OpenSession()
  {
    Configuration config;
    ISessionFactory factory;
    ISession session;
    config = new Configuration();

    if (config == null)
    {
      throw new ArgumentNullException(nameof(config));
    }
    if (factory == null)
    {
      throw new ArgumentNullException(nameof(factory);
    }
    if (session == null)
    {
      throw new ArgumentNullException(nameof(session));
    }

    config.AddAssembly("My.Assembly.Here");
    factory = config.BuildSessionFactory();
    session = factory.OpenSession();
    
    return session;
  }
} 
如果有帮助,请告诉我。

退房。他的早期版本有一些限制,你需要纠正关闭和刷新的错误处理,我不确定我是否正确,但我会发布我如何修改他的东西

Billy还在开发一个使用MVC和nHibernate的新框架,名为S,我目前正在使用这个框架,目前为止还不错

无论如何,这是我对他的代码的修改版本。我对准确性或完整性不做任何保证,而您使用此功能的风险由您自己承担。如果使用此选项,请确保关闭会话。如果你有任何问题,给我发一封电子邮件[joshua][dot][berke],邮箱地址是[gmail…其余的你都知道]

/// <summary>
/// Handles creation and management of sessions and transactions.  It is a singleton because 
/// building the initial session factory is very expensive. Inspiration for this class came 
/// from Chapter 8 of Hibernate in Action by Bauer and King.  Although it is a sealed singleton
/// you can use TypeMock (http://www.typemock.com) for more flexible testing.
/// </summary>
public sealed class NHibernateSessionManager
{
    private const string DefaultConfigFile = "DefaultAppWeb.Config";
    private static readonly object _syncRoot = new object();
    #region Thread-safe, lazy Singleton

/// <summary>
/// This is a thread-safe, lazy singleton.  See http://www.yoda.arachsys.com/csharp/singleton.html
/// for more details about its implementation.
/// </summary>
public static NHibernateSessionManager Instance
{
    get
    {
        return Nested.NHibernateSessionManager;
    }
}

/// <summary>
/// Private constructor to enforce singleton
/// </summary>
private NHibernateSessionManager() { }

/// <summary>
/// Assists with ensuring thread-safe, lazy singleton
/// </summary>
private class Nested
{
    static Nested() { }
    internal static readonly NHibernateSessionManager NHibernateSessionManager =
        new NHibernateSessionManager();
}

#endregion

/// <summary>
/// This method attempts to find a session factory stored in <see cref="sessionFactories" />
/// via its name; if it can't be found it creates a new one and adds it the hashtable.
/// </summary>
/// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
{
    Check.Require(!string.IsNullOrEmpty(sessionFactoryConfigPath),
        "sessionFactoryConfigPath may not be null nor empty");

    //  Attempt to retrieve a stored SessionFactory from the hashtable.
    ISessionFactory sessionFactory;// = (ISessionFactory)sessionFactories[sessionFactoryConfigPath];

    //  try and get a session factory if we don't find one create it
    lock (_syncRoot)
    {
        if (!sessionFactories.TryGetValue(sessionFactoryConfigPath, out sessionFactory))
        {
            Configuration cfg = new Configuration();
            if (sessionFactoryConfigPath != DefaultConfigFile)
            {
                Check.Require(File.Exists(sessionFactoryConfigPath),
                    "The config file at '" + sessionFactoryConfigPath + "' could not be found");
                cfg.Configure(sessionFactoryConfigPath);


            }
            else
            {
                cfg.Configure();
            }


            //  Now that we have our Configuration object, create a new SessionFactory
            sessionFactory = cfg.BuildSessionFactory();


            Check.Ensure(sessionFactory != null, "sessionFactory is null and was not built");
            sessionFactories.Add(sessionFactoryConfigPath, sessionFactory);
        }
    }



    return sessionFactory;
}

/// <summary>
/// Allows you to register an interceptor on a new session.  This may not be called if there is already
/// an open session attached to the HttpContext.  If you have an interceptor to be used, modify
/// the HttpModule to call this before calling BeginTransaction().
/// </summary>
public void RegisterInterceptorOn(string sessionFactoryConfigPath, IInterceptor interceptor)
{
    ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];

    if (session != null && session.IsOpen)
    {
        throw new CacheException("You cannot register an interceptor once a session has already been opened");
    }

    GetSessionFrom(sessionFactoryConfigPath, interceptor);
}

public ISession GetSessionFrom(string sessionFactoryConfigPath)
{
    return GetSessionFrom(sessionFactoryConfigPath, null);
}
/// <summary>
/// Gets or creates an ISession using the web / app config file.
/// </summary>
/// <returns></returns>
public ISession GetSessionFrom()
{
    return GetSessionFrom(DefaultConfigFile, null);
}
/// <summary>
/// Gets a session with or without an interceptor.  This method is not called directly; instead,
/// it gets invoked from other public methods.
/// </summary>
private ISession GetSessionFrom(string sessionFactoryConfigPath, IInterceptor interceptor)
{
    var allSessions = ContextSessions;
    ISession session = null;
    if (!allSessions.TryGetValue(sessionFactoryConfigPath, out session))
    {
        if (interceptor != null)
        {
            session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(interceptor);
        }
        else
        {
            session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();
        }

        allSessions[sessionFactoryConfigPath] = session;
    }

    //session.FlushMode = FlushMode.Always;

    Check.Ensure(session != null, "session was null");

    return session;
}

/// <summary>
/// Flushes anything left in the session and closes the connection.
/// </summary>
public void CloseSessionOn(string sessionFactoryConfigPath)
{
    ISession session;
    if (ContextSessions.TryGetValue(sessionFactoryConfigPath, out session))
    {
        if (session.IsOpen)
        {
            session.Flush();
            session.Close();
        }
        ContextSessions.Remove(sessionFactoryConfigPath);

    }

}

public ITransaction BeginTransactionOn(string sessionFactoryConfigPath)
{
    ITransaction transaction;

    if (!ContextTransactions.TryGetValue(sessionFactoryConfigPath, out transaction))
    {
        transaction = GetSessionFrom(sessionFactoryConfigPath).BeginTransaction();
        ContextTransactions.Add(sessionFactoryConfigPath, transaction);
    }

    return transaction;
}

public void CommitTransactionOn(string sessionFactoryConfigPath)
{

    try
    {
        if (HasOpenTransactionOn(sessionFactoryConfigPath))
        {
            ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

            transaction.Commit();
            ContextTransactions.Remove(sessionFactoryConfigPath);
        }
    }
    catch (HibernateException he)
    {
        try
        {
            RollbackTransactionOn(sessionFactoryConfigPath);
        }
        finally
        {
            throw he;
        }
    }
}

public bool HasOpenTransactionOn(string sessionFactoryConfigPath)
{
    ITransaction transaction;
    if (ContextTransactions.TryGetValue(sessionFactoryConfigPath, out transaction))
    {

        return !transaction.WasCommitted && !transaction.WasRolledBack;
    }
    return false;
}

public void RollbackTransactionOn(string sessionFactoryConfigPath)
{

    try
    {
        if (HasOpenTransactionOn(sessionFactoryConfigPath))
        {
            ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

            transaction.Rollback();
        }

        ContextTransactions.Remove(sessionFactoryConfigPath);
    }
    finally
    {

        ForceCloseSessionOn(sessionFactoryConfigPath);
    }
}

/// <summary>
/// Since multiple databases may be in use, there may be one transaction per database 
/// persisted at any one time.  The easiest way to store them is via a hashtable
/// with the key being tied to session factory.  If within a web context, this uses
/// <see cref="HttpContext" /> instead of the WinForms specific <see cref="CallContext" />.  
/// Discussion concerning this found at http://forum.springframework.net/showthread.php?t=572
/// </summary>
private Dictionary<string, ITransaction> ContextTransactions
{
    get
    {
        if (IsInWebContext())
        {
            if (HttpContext.Current.Items[TRANSACTION_KEY] == null)
                HttpContext.Current.Items[TRANSACTION_KEY] = new Dictionary<string, ITransaction>();

            return (Dictionary<string, ITransaction>)HttpContext.Current.Items[TRANSACTION_KEY];
        }
        else
        {
            if (CallContext.GetData(TRANSACTION_KEY) == null)
                CallContext.SetData(TRANSACTION_KEY, new Dictionary<string, ITransaction>());

            return (Dictionary<string, ITransaction>)CallContext.GetData(TRANSACTION_KEY);
        }
    }
}

/// <summary>
/// Since multiple databases may be in use, there may be one session per database 
/// persisted at any one time.  The easiest way to store them is via a hashtable
/// with the key being tied to session factory.  If within a web context, this uses
/// <see cref="HttpContext" /> instead of the WinForms specific <see cref="CallContext" />.  
/// Discussion concerning this found at http://forum.springframework.net/showthread.php?t=572
/// </summary>
private Dictionary<string, ISession> ContextSessions
{
    get
    {
        if (IsInWebContext())
        {
            if (HttpContext.Current.Items[SESSION_KEY] == null)
                HttpContext.Current.Items[SESSION_KEY] = new Dictionary<string, ISession>();

            return (Dictionary<string, ISession>)HttpContext.Current.Items[SESSION_KEY];
        }
        else
        {
            if (CallContext.GetData(SESSION_KEY) == null)
                CallContext.SetData(SESSION_KEY, new Dictionary<string, ISession>());

            return (Dictionary<string, ISession>)CallContext.GetData(SESSION_KEY);
        }
    }
}

private bool IsInWebContext()
{
    return HttpContext.Current != null;
}

private Dictionary<string, ISessionFactory> sessionFactories = new Dictionary<string, ISessionFactory>();
private const string TRANSACTION_KEY = "CONTEXT_TRANSACTIONS";
private const string SESSION_KEY = "CONTEXT_SESSIONS";

public bool HasOpenTransactionOn()
{
    return HasOpenTransactionOn(DefaultConfigFile);
}

public void CommitTransactionOn()
{
    CommitTransactionOn(DefaultConfigFile);
}

public void CloseSessionOn()
{
    CloseSessionOn(DefaultConfigFile);
}

public void ForceCloseSessionOn()
{
    ForceCloseSessionOn(DefaultConfigFile);

}

public void ForceCloseSessionOn(string sessionFactoryConfigPath)
{
    ISession session;
    if (ContextSessions.TryGetValue(sessionFactoryConfigPath, out session))
    {
        if (session.IsOpen)
        {

            session.Close();
        }
        ContextSessions.Remove(sessionFactoryConfigPath);

    }
}

public void BeginTransactionOn()
{
    this.BeginTransactionOn(DefaultConfigFile);
}

public void RollbackTransactionOn()
{
    this.RollbackTransactionOn(DefaultConfigFile);
}
//
///处理会话和事务的创建和管理。这是一个单身汉,因为
///构建初始会话工厂非常昂贵。这门课的灵感来了
///出自鲍尔和金的《冬眠行动》第八章。虽然它是一个封闭的单身汉
///您可以使用TypeMock(http://www.typemock.com)用于更灵活的测试。
/// 
公共密封类NHibernateSessionManager
{
private const string DefaultConfigFile=“DefaultAppWeb.Config”;
私有静态只读对象_syncRoot=新对象();
#区域线程安全、懒惰的单例
/// 
///这是一个线程安全的懒惰单例。请参阅http://www.yoda.arachsys.com/csharp/singleton.html
///有关其实现的更多详细信息。
/// 
公共静态NHibernateSessionManager实例
{
得到
{
返回Nested.NHibernateSessionManager;
}
}
/// 
///强制单例的私有构造函数
/// 
私有NHibernateSessionManager(){}
/// 
///协助确保线程安全、懒惰的单例
/// 
私有类嵌套
{
静态嵌套(){}
内部静态只读NHibernateSessionManager NHibernateSessionManager=
新的NHibernateSessionManager();
}
#端区
/// 
///此方法尝试查找存储在中的会话工厂
///通过它的名称;如果找不到它,它将创建一个新的并将其添加到哈希表中。
/// 
///工厂配置的路径位置
私有ISessionFactory GetSessionFactoryFor(字符串sessionFactoryConfigPath)
{
Check.Require(!string.IsNullOrEmpty(sessionFactoryConfigPath),
“sessionFactoryConfigPath不能为null或空”);
//尝试从哈希表中检索存储的SessionFactory。
ISessionFactory sessionFactory;//=(ISessionFactory)sessionFactory[sessionFactoryConfigPath];
//如果找不到会话工厂,请尝试创建会话工厂
锁定(\u syncRoot)
{
if(!sessionFactories.TryGetValue(sessionFactoryConfigPath,out sessionFactory))
{
Configuration cfg=新配置();
if(sessionFactoryConfigPath!=DefaultConfigFile)
{
Check.Require(文件.Exists(sessionFactoryConfigPath)),
“找不到位于“+sessionFactoryConfigPath+”的配置文件”);
Configure(sessionFactoryConfigPath);
}
其他的
{
Configure();
}
//现在我们有了配置对象,创建一个新的SessionFactory
sessionFactory=cfg.BuildSessionFactory();
检查。确保(sessionFactory!=null,“sessionFactory为null且未生成”);
添加(sessionFactoryConfigPath,sessionFactory);
}
}
返回工厂;
}
/// 
///允许您在新会话上注册拦截器。如果已有拦截器,则可能不会调用该拦截器
///连接到HttpContext的打开会话。如果要使用拦截器,请修改
///在调用BeginTransaction()之前调用此函数的HttpModule。
/// 
public void RegisterInterceptorOn(字符串sessionFactoryConfigPath,IIInterceptor侦听器)
{
ISession session=(ISession)ContextSessions[sessionFactoryConfigPath];
if(session!=null&&session.IsOpen)
{
抛出新的CacheException(“一旦会话已经打开,就不能注册拦截器”);
}
GetSessionFrom(sessionFactoryConfigPath,拦截器);
}
公共ISession GetSessionFrom(字符串sessionFactoryConfigPath)
{
返回GetSessionFrom(sessionFactoryConfigPath,null);
}
/// 
///使用web/app配置文件获取或创建ISession。
/// 
/// 
公共ISession GetSessionFrom()
{
返回GetSessionFrom(DefaultConfigFile,null);
}
/// 
///获取包含或不包含拦截器的会话。此方法不是直接调用的,而是,
///它从其他公共方法调用。
/// 
私有ISession GetSessionFrom(字符串sessionFactoryConfigPath,IInterceptor侦听器)
{
var allSessions=ContextSessions;
ISession session=null;
if(!allSessions.TryGetValue(sessionFactoryConfigPath,out session))
{
if(拦截器!=null)
{
会话=GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(拦截器);
}
其他的
{
session=GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();
}
所有会话[sessionFactoryConfigPath]=会话;
}
//session.FlushMode=FlushMode.Always;
检查。确保(会话!=null,“会话为null”);
返回会议;
}
/// 
///刷新会话中剩余的任何内容并关闭连接。
/// 
public void CloseSessionOn(字符串sessionFactoryConfigPath)
{
闭会期间会议;
if(ContextSessions.TryGetValue(sessionFactoryConfigPath,out session))
{
if(session.IsOpen)
{
session.Flush();
session.Close();
}
ContextSessions.Remove(会话)