2012-02-03 100 views
0

我想用線程創建迷你會話和完全工廠。完整的會議工廠在第二個線程上。這個概念是用最小限度的做最初的登錄細節,並等待其他事情全面激情。我實現了線程,但是當代碼碰到buildsessionfactory(第二個)時出現了一些問題。當不在線程上時,代碼工作正常。我如何爲登錄細節等活動實施minisession。我認爲其中一個問題也是如何啓動線程(GetFullSessionFactoryFor)。迷你會話工廠和realsession工廠

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; 
} 
+2

不要。只是...不。 – 2012-02-03 19:16:58

回答

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 
} 
+0

arent你在這裏添加一些線程 – arjun 2012-02-03 14:59:55

+0

爲什麼?當你需要結果並等待它完成時,你開始線程,基本上和不使用線程一樣。爲了加快速度(這很少需要),你必須首先啓動線程才能真正使用結果,但由於您不知道在運行時使用哪些工廠,因此在啓動時如何創建它們? – Firo 2012-02-03 15:27:14

+0

感謝您的建議和幫助。我正在使用flent nhibernate做一個wpf應用程序。實際上這個要求是創造迷你和全面的激情。迷你會話工廠僅用於登錄詳細信息,直到完整會話準備就緒。如果必須使用線程來完成,你將如何實現它。假設用戶類需要minisession工廠。剩下的實體等待全面啓動。在哪裏你將如何開始線程。請給出一個例子,你將如何開始線程 – arjun 2012-02-05 04:03:46