NHibernate-用于管理SessionFactory/Session的良好,完整的工作Helper类 [英] NHibernate - good complete working Helper class for managing SessionFactory/Session

查看:52
本文介绍了NHibernate-用于管理SessionFactory/Session的良好,完整的工作Helper类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

can anyone provide/refer a proper OO type helper class for managing a singleton of the SessionFactory and then also for managing Sessions?

推荐答案

查看 Billy麦卡菲蒂的作品.他的早期版本有一些局限性,您需要更正关闭和刷新时的错误处理,但我不确定我是否正确,但是我将发布如何修改他的内容.

Check out Billy McCafferty's work. His earlier version had some limitations, you'll need to correct the error handling around closing and flushing, and I'm not sure i have it right but I will post how I modified his stuff.

Billy还正在研究使用MVC& amp;的新框架. nHibernate调用了我目前正在使用的S #arp Architechure 好的.

Billy is also working on a new framework that uses MVC & nHibernate called S#arp Architechure which I'm currently using, and so far so good.

无论如何,这是我修改后的代码版本.对于准确性或完整性,我不做任何旁白,请您自担风险.如果使用此功能,请确保关闭会话.如果您有任何疑问,请给我发一封电子邮件,地址为[gmail ....您知道其余的内容] [joshua] [dot] [berke].

Anyways here's my modified version of his code. I make no guanrtees on accuracy or completness and you are using this on your own risk. If you use this make sure you close the session out. If you have any questions drop me an email [joshua][dot][berke] at [gmail...you know the rest].

/// <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);
}

}

这篇关于NHibernate-用于管理SessionFactory/Session的良好,完整的工作Helper类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆