迷你会议工厂和realsession工厂

时间:2012-02-03 11:00:10

标签: nhibernate fluent-nhibernate

我想使用线程创建迷你会话和fullsession工厂。完整的会话工厂在第二个线程。这个概念是用minisession做初始登录细节,等待其他事情的完整。我实现了线程,但是当代码遇到buildsessionfactory时(​​第二个)存在一些问题。当不在线程上代码工作正常。我如何实现minisession仅用于登录详细信息等活动。我认为其中一个问题也是如何启动线程(GetFullSessionFactoryFor)。

  public sealed class NHibernateSessionManager
    {
    static bool sessionFactoryReady = false;
    #region Thread-safe, lazy Singleton
    private string _sessionFactoryConfigPath = null;

    public static NHibernateSessionManager Instance
    {
        get
        {
            return Nested.NHibernateSessionManager;
        }
    }


    private NHibernateSessionManager() { }


    private class Nested
    {
        static Nested() { }
        internal static readonly NHibernateSessionManager NHibernateSessionManager =
            new NHibernateSessionManager();
    }

    #endregion


    private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
    {
        GetFullSessionFactoryFor(sessionFactoryConfigPath);
        while (!sessionFactoryReady) Thread.Sleep(10000);
        return (ISessionFactory)sessionFactories[sessionFactoryConfigPath];
    }

    private void GetFullSessionFactoryFor(string sessionFactoryConfigPath)
    {
        ThreadPool.QueueUserWorkItem(state =>
         {
        Check.Require(!string.IsNullOrEmpty(sessionFactoryConfigPath),
                      "sessionFactoryConfigPath may not be null nor empty");



        ISessionFactory sessionFactory = (ISessionFactory)sessionFactories[sessionFactoryConfigPath];


        if (sessionFactory == null)
        {
            Check.Require(File.Exists(sessionFactoryConfigPath),
                          "The config file at '" + sessionFactoryConfigPath + "' could not be found");

            Configuration cfg = new Configuration();
            cfg.SetInterceptor(new NHInterceptor());
            cfg.Configure(sessionFactoryConfigPath);



            FluentConfiguration fluentConfiguration = Fluently.Configure(cfg)
                .Mappings(m =>
                {
                    m.FluentMappings
                         .AddFromAssembly(Assembly.Load("someassembly"))
                         .Conventions.Add(DefaultLazy.Always(),
                                          OptimisticLock.Is(x => x.All()),
                                          DynamicUpdate.AlwaysTrue(),
                                          DynamicInsert.AlwaysFalse(),
                                          DefaultCascade.None()
                                         )
                         .Conventions.AddFromAssemblyOf<"someDateconventionobject">()
                         ;
                });


            ;
            sessionFactory = fluentConfiguration.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
            }

            sessionFactories.Add(sessionFactoryConfigPath, sessionFactory);


            cfg.SetInterceptor(new NHInterceptor());
            cfg.Configure(sessionFactoryConfigPath);

            fluentConfiguration = Fluently.Configure(cfg);

            string userDataPath = cfg.GetProperty("connection.connection_string").ToUpper();
            userDataPath = userDataPath.Replace("somevalue", "");
            userDataPath = userDataPath.Replace(";somevalue", "");


            string[] folderList = System.IO.Directory.GetDirectories(userDataPath);
            bool firstFolder = true;

            foreach (string folder in folderList)
            {
                if (System.IO.File.Exists(folder + "\\somedatabase"))
                {

                    try
                    {
                        if (firstFolder)
                        {

                            fluentConfiguration = fluentConfiguration.ExposeConfiguration(c => c.SetProperty("sessionfactoryname", folder.ToLower()))
                                .ExposeConfiguration(c => c.SetProperty("connectionstring", ""))
                                .Mappings(m =>
                                {
                                    m.FluentMappings
                                        .AddFromAssembly(Assembly.Load("otherassembly"))
                                        .Conventions.Add(DefaultLazy.Always(),
                                                         OptimisticLock.Is(x => x.All()),
                                                         DynamicUpdate.AlwaysTrue(),
                                                         DynamicInsert.AlwaysFalse(),
                                                         DefaultCascade.None()
                                                        )
                                        .Conventions.AddFromAssemblyOf<"somedateconventionobject">()
                                        ;
                                }
                                         )
                                ;


                        }
                        else
                        {
                            fluentConfiguration = fluentConfiguration.ExposeConfiguration(c => c.SetProperty("sessionfactoryname", "name"))
                                .ExposeConfiguration(c => c.SetProperty("connectionstring", "value"));
                        }

                        sessionFactory = fluentConfiguration.BuildSessionFactory(); ------here is the problem
                        sessionFactories.Add(folder.ToLower(), sessionFactory);
                    }
                    catch (Exception e)
                    {
                        throw new EncoreException(e);
                    }

                }
            }
        }

        sessionFactoryReady = true;

        });

    }


    public void RegisterInterceptorOn(string sessionFactoryConfigPath, IInterceptor interceptor, int sessionId)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

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

        GetSessionFrom(sessionFactoryConfigPath, interceptor, sessionId);
    }

    public ISession GetSessionFrom(string sessionFactoryConfigPath, int sessionId)
    {
        return GetSessionFrom(sessionFactoryConfigPath, null, sessionId);
    }


    private ISession GetSessionFrom(string sessionFactoryConfigPath, IInterceptor interceptor, int sessionId)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

        if (session == null)
        {
            if (interceptor != null)
            {
                session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(interceptor);
            }
            else
            {
                session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();
            }
            session.FlushMode = FlushMode.Never;
            ContextSessions[sessionFactoryConfigPath + "//" + sessionId.ToString()] = session;
        }

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

        return session;
    }


    public System.Data.IDbConnection GetDbConnection(string sessionFactoryConfigPath, int sessionId)
    {
        ISession session = GetSessionFrom(sessionFactoryConfigPath, sessionId);
        return session.Connection;
    }


    public void CloseSessionOn(string sessionFactoryConfigPath, int sessionId)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

        if (session != null && session.IsOpen)
        {

            session.Close();


            sessionList[sessionId] = false;
            reuseSessionList.Push(sessionId);
        }

        ContextSessions.Remove(sessionFactoryConfigPath + "//" + sessionId.ToString());
    }

    public ITransaction BeginTransactionOn(string sessionFactoryConfigPath, int sessionId)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

        if (transaction == null)
        {
            transaction = GetSessionFrom(sessionFactoryConfigPath, sessionId).BeginTransaction();
            ContextTransactions.Add(sessionFactoryConfigPath + "//" + sessionId.ToString(), transaction);
        }

        return transaction;
    }

    public void CommitTransactionOn(string sessionFactoryConfigPath, int sessionId)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

        try
        {
            if (HasOpenTransactionOn(sessionFactoryConfigPath, sessionId))
            {
                transaction.Commit();
                ContextTransactions.Remove(sessionFactoryConfigPath + "//" + sessionId.ToString());
            }
        }
        catch (HibernateException)
        {
            RollbackTransactionOn(sessionFactoryConfigPath, sessionId);
            throw;
        }
    }

    public bool HasOpenTransactionOn(string sessionFactoryConfigPath, int sessionId)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

        return transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack;
    }

    public void RollbackTransactionOn(string sessionFactoryConfigPath, int sessionId)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath + "//" + sessionId.ToString()];

        try
        {
            if (HasOpenTransactionOn(sessionFactoryConfigPath, sessionId))
            {
                transaction.Rollback();
            }

            ContextTransactions.Remove(sessionFactoryConfigPath + "//" + sessionId.ToString());
        }
        finally
        {

        }
    }
    public int GetSession()
    {
        int getSessionId = 0;
        if (reuseSessionList.Count > 0)
        {
            getSessionId = reuseSessionList.Pop();
            sessionList[getSessionId] = true;
        }
        else
        {
            getSessionId = nextSessionId;
            sessionList.Add(true);
            nextSessionId++;
        }
        return getSessionId;

    }




    private Hashtable ContextTransactions
    {
        get
        {
            if (IsInWebContext())
            {
                if (HttpContext.Current.Items[TRANSACTION_KEY] == null)
                    HttpContext.Current.Items[TRANSACTION_KEY] = new Hashtable();

                return (Hashtable)HttpContext.Current.Items[TRANSACTION_KEY];
            }
            else
            {
                if (CallContext.GetData(TRANSACTION_KEY) == null)
                    CallContext.SetData(TRANSACTION_KEY, new Hashtable());

                return (Hashtable)CallContext.GetData(TRANSACTION_KEY);
            }
        }
    }


    private Hashtable ContextSessions
    {
        get
        {
            if (IsInWebContext())
            {
                if (HttpContext.Current.Items[SESSION_KEY] == null)
                    HttpContext.Current.Items[SESSION_KEY] = new Hashtable();

                return (Hashtable)HttpContext.Current.Items[SESSION_KEY];
            }
            else
            {
                if (CallContext.GetData(SESSION_KEY) == null)
                    CallContext.SetData(SESSION_KEY, new Hashtable());

                return (Hashtable)CallContext.GetData(SESSION_KEY);
            }
        }
    }

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

    private Hashtable sessionFactories = new Hashtable();
    private const string TRANSACTION_KEY = "CONTEXT_TRANSACTIONS";
    private const string SESSION_KEY = "CONTEXT_SESSIONS";

    private List<bool> sessionList = new List<bool>();
    private Stack<int> reuseSessionList = new Stack<int>();
    private int nextSessionId = 0;
}

1 个答案:

答案 0 :(得分:0)

  • firstFolder永远不会设置为false,因此为每个子文件夹添加了映射,并且延长了sessionfactory的创建。
  • 应该省略GetDbConnection。它很简单GetSessionFrom().Connection甚至更好GetSessionFrom().CreateSqlQuery()所以没有获得任何价值
  • 线程根本不添加任何值,因为所有值都是懒惰创建的。
  • 会话已经拥有唯一ID,无需自行管理。

我不明白你的子目录的逻辑,所以我把它们排除在外。如果你解释这个想法,我可以看看我是否可以拿出更好的代码来处理它们

您的代码的修订版

public sealed class NHibernateSessionManager
{
    // Constants
    private const string FACTORY_KEY = "CONTEXT_FACTORIES";
    private const string SESSION_KEY = "CONTEXT_SESSIONS";
    private const string TRANSACTION_KEY = "CONTEXT_TRANSACTIONS";

    private IDictionary<string, ISessionFactory> SessionFactories = new Dictionary<string, ISessionFactory>();

    // not really nessesary because creating NHibernateSessionManager is very cheap
    #region Thread-safe, lazy Singleton
    private NHibernateSessionManager() { }

    public static NHibernateSessionManager Instance
    {
        get { return Nested.NHibernateSessionManager; }
    }

    private class Nested
    {
        static Nested() { }
        internal static readonly NHibernateSessionManager NHibernateSessionManager =
            new NHibernateSessionManager();
    }

    #endregion

    private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
    {
        Check.Require(!string.IsNullOrEmpty(sessionFactoryConfigPath), "sessionFactoryConfigPath may not be null nor empty");

        ISessionFactory sessionFactory = SessionFactories[sessionFactoryConfigPath];

        if (sessionFactory == null)
        {
            // logic to configure and build the factory

            Check.Require(File.Exists(sessionFactoryConfigPath),
                "The config file at '" + sessionFactoryConfigPath + "' could not be found");

            Configuration cfg = new Configuration()
                .Configure(sessionFactoryConfigPath)
                .SetInterceptor(new NHInterceptor());

            string assemblypath = Path.Combine(Path.GetDirectoryName(sessionFactoryConfigPath), "whatever");
            Assembly assembly = Assembly.Load(assemblypath);
            sessionFactory = Fluently.Configure(cfg)
                .Mappings(m => m.FluentMappings
                            .AddFromAssembly(assembly)
                            .Conventions.Add(
                                DefaultLazy.Always(),
                                OptimisticLock.Is(x => x.All()),
                                DynamicUpdate.AlwaysTrue(),
                                DynamicInsert.AlwaysFalse(),
                                DefaultCascade.None())
                            .Conventions.AddAssembly(assembly))
                .BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
            }
            SessionFactories.Add(sessionFactoryConfigPath, sessionFactory);

            // !!!DirectoryLogic ommitted because doesn't understand at all!!!
        }
        return sessionFactory;
    }

    private IDictionary<Guid, ISession> Sessions
    {
        get
        {
            if (IsInWebContext())
            {
                if (HttpContext.Current.Items[SESSION_KEY] == null)
                    HttpContext.Current.Items[SESSION_KEY] = new Dictionary<Guid, ISession>();

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

                return (IDictionary<Guid, ISession>)CallContext.GetData(SESSION_KEY);
            }
        }
    }

    private IDictionary<Guid, ITransaction> Transactions
    {
        get
        {
            if (IsInWebContext())
            {
                if (HttpContext.Current.Items[TRANSACTION_KEY] == null)
                    HttpContext.Current.Items[TRANSACTION_KEY] = new Dictionary<Guid, ITransaction>();

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

                return (IDictionary<Guid, ITransaction>)CallContext.GetData(TRANSACTION_KEY);
            }
        }
    }

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

    #region public

    public Guid CreateSessionFor(string sessionFactoryConfigPath)
    {
        return CreateSessionFor(sessionFactoryConfigPath, null);
    }

    public Guid CreateSessionFor(string sessionFactoryConfigPath, IInterceptor interceptor)
    {
        var factory = SessionFactories[sessionFactoryConfigPath];
        if (factory == null)
        {
            factory = GetSessionFactoryFor(sessionFactoryConfigPath);
            SessionFactories[sessionFactoryConfigPath] = factory;
        }
        ISession session;
        if (interceptor != null)
            session = factory.OpenSession(interceptor);
        else
            session = factory.OpenSession();

        Guid sessionId = session.GetSessionImplementation().SessionId;
        Sessions.Add(sessionId, session);

        return sessionId;
    }

    public ISession GetSession(Guid sessionId)
    {
        var session = Sessions[sessionId];
        Check.Ensure(session != null, "there is no session with id '" + sessionId + "'");

        return session;
    }

    public void CloseSession(Guid sessionId)
    {
        ISession session = Sessions[sessionId];

        if (session != null && session.IsOpen)
        {
            session.Close();
        }

        Sessions.Remove(sessionId);
    }

    public ITransaction BeginTransactionOn(Guid sessionId)
    {
        ITransaction transaction = Transactions[sessionId];

        if (transaction == null)
        {
            transaction = GetSession(sessionId).BeginTransaction();
            Transactions.Add(sessionId, transaction);
        }

        return transaction;
    }

    public void CommitTransactionOn(Guid sessionId)
    {
        ITransaction transaction = Transactions[sessionId];

        try
        {
            if (transaction != null && transaction.IsActive)
            {
                transaction.Commit();
            }
        }
        catch (HibernateException)
        {
            transaction.Rollback();
            throw;
        }
        finally
        {
            Transactions.Remove(sessionId);
        }
    }

    public void RollbackTransactionOn(Guid sessionId)
    {
        ITransaction transaction = Transactions[sessionId];

        try
        {
            if (transaction != null && transaction.IsActive)
            {
                transaction.Rollback();
            }
        }
        finally
        {
            Transactions.Remove(sessionId);

        }
    }
    #endregion
}