2012-07-18 65 views
0

我可能錯過了在波紋管代碼中跟蹤的內容,但它會減慢遠程數據庫服務器的響應時間。當應用程序部署在同一臺機器上的數據庫中嘗試時,應用程序工作正常。另外,使用NH-Profiler驗證所有nHibernate任務。所有查詢都受到控制。唯一的原因是數據庫服務器的響應時間。此外,分析數據庫服務器,服務器是好的,但這是通過遠程數據庫服務器運行速度慢的唯一應用程序。遠程數據庫響應使用NHIbernate的asp.net應用程序的速度非常慢

以下是的通用類,用於所有NHibernate的操作:我們使用流利的映射

public static bool CheckIfUserNameAlreadyExists(string username) 
    { 
     bool isExist; 
     using (var userRepo = new CommonRepository()) 
     { 
      isExist = userRepo.FindBySpecificColumn<User>("LoginId", username) != null; 
     } 
     return isExist; 
    } 

public class CommonRepository : IDisposable 
    { 
     protected static Configuration Config; 
     protected static ISessionFactory SessionFactory; 
     protected static ITransaction Transaction; 
     static readonly object Factorylock = new object(); 

     /// <summary> 
     /// Configure your repositories. It uses default DB string 
     /// Create singleton thread safe : found good stuff on Stackoverflow 
     /// Referrence : http://stackoverflow.com/questions/2362195/ensure-nhibernate-sessionfactory-is-only-created-once 
     /// </summary> 
     public CommonRepository() 
     { 
      lock (Factorylock) 
      { 
       if (SessionFactory == null) 
       { 
        // SessionFactory = NonFluentConfiguration(); 
        SessionFactory = FluentConfig(msdnh.util.Config.ConnectionString); //Grab default string from Database 
       } 
      } 

      Session = SessionFactory.OpenSession(); 
      Transaction = Session.BeginTransaction(); 

     } 

     /// <summary> 
     /// Configure your repositories 
     /// </summary> 
     /// <param name="connectionString">Connection string</param> 
     public CommonRepository(string connectionString) 
     { 
      if (SessionFactory == null) 
      { 
       SessionFactory = FluentConfig(connectionString); 
      } 
      Session = SessionFactory.OpenSession(); 
      Transaction = Session.BeginTransaction(); 
     } 
     private static ISessionFactory NonFluentConfiguration() 
     { 
      Config = new Configuration(); 
      Config.Configure(); 
      Config.AddAssembly(typeof(CommonRepository).Assembly); 
      return Config.BuildSessionFactory(); 
     } 

     private static ISessionFactory FluentConfig(string connString) 
     { 

      IPersistenceConfigurer persistenceConfigurer = 
       MsSqlConfiguration 
        .MsSql2008 
       .ConnectionString(connString) 
       .ShowSql(); 

      // initialize nhibernate with persistance configurer properties 
      Configuration cfg = persistenceConfigurer 
       .ConfigureProperties(new Configuration()); 

      // add mappings definition to nhibernate configuration 
      var persistenceModel = new PersistenceModel(); 
      persistenceModel.AddMappingsFromAssembly(Assembly.Load("Girlpower")); 
      persistenceModel.Configure(cfg); 

      // set session factory field which is to be used in tests 
      return cfg.BuildSessionFactory(); 


     } 

     protected static ISession Session { get; private set; } 
     public bool Commit() 
     { 
      if (Transaction.IsActive) 
      { 
       try { Transaction.Commit(); return true; } 
       catch (Exception exception) 
       { 
        //Error log 
        return false; 

       } 
      } 
      return false; 
     } 
     public bool Rollback() 
     { 
      if (Transaction.IsActive) 
      { 
       try { Transaction.Rollback(); return true; } 
       catch (Exception exception) 
       { 
        //Error log 
        return false; 
       } 
      } 
      return false; 
     } 
     public void GenerateSchema() 
     { 
      new SchemaExport(Config).Execute(true, false, false); 
     } 
     private void BuildSchema(Configuration cfg) 
     { 
      new SchemaExport(cfg) 
       .Create(false, true); 
     } 

     #region Repository Functions 
     /// <summary> 
     /// Saves or updates the object to the database, depending on the value of its identifier property. 
     /// </summary> 
     /// <param name="value"> 
     /// A transient instance containing a new or updated state.</param> 
     public void Save(object value) 
     { 
      Session.Save(value); 
     } 
     /// <summary> 
     /// Save object to repository 
     /// </summary> 
     /// <param name="value"> 
     /// Object for save</param> 
     public void SaveorUpdate(object value) 
     { 
      Session.SaveOrUpdate(value); 
     } 
     /// <summary> 
     /// Merge/copy state of given object to persit object 
     /// </summary> 
     /// <param name="value">Entity</param> 
     public void SaveorUpdateCopy(object value) 
     { 
      Session.Merge(value); 
     } 
     /// <summary> 
     /// Removes a persistent instance from the database. 
     /// </summary> 
     /// <param name="value"> 
     /// The instance to be removed.</param> 
     public void Delete(object value) 
     { 
      Session.Delete(value); 
     } 
     /// <summary> 
     /// Delete records from specific entity 
     /// </summary> 
     /// <typeparam name="T">Entity name</typeparam> 
     /// <param name="id">value of record id</param> 
     public void Delete<T>(int id) where T : class 
     { 
      Session.Delete(string.Format("from {0} where id = {1}", typeof(T), id)); 

     } 
     /// <summary> 
     /// Update specific fields of entity using IQuery 
     /// </summary> 
     /// <typeparam name="T"></typeparam> 
     /// <param name="id"></param> 
     /// <param name="updateColName"></param> 
     /// <param name="updateColValue"></param> 
     public void Update<T>(int id, string updateColName, object updateColValue) where T : class 
     { 
      var query = CreateQuery<T>(id, updateColName, updateColValue); 
      query.ExecuteUpdate(); 
     } 

     private static IQuery CreateQuery<T>(int id, string updateColName, object updateColValue) where T : class 
     { 
      return Session.CreateQuery(string.Format("Update {0} set {1} = {2} where id = {3} ", typeof(T), updateColName, updateColValue, id)); 
     } 

     /// <summary> 
     /// Delete records from specific entity by speciying column name 
     /// </summary> 
     /// <typeparam name="T"></typeparam> 
     /// <param name="id"></param> 
     /// <param name="colName"></param> 
     public void Delete<T>(int id, string colName) where T : class 
     { 
      Session.Delete(string.Format("from {0} where {1} = {2}", typeof(T), colName, id)); 

     } 
     /// <summary> 
     /// Returns a strong typed persistent instance of the given named entity with the given identifier, or null if there is no such persistent instance. 
     /// </summary> 
     /// <typeparam name="T">The type of the given persistant instance.</typeparam> 
     /// <param name="id">An identifier.</param> 
     public T Get<T>(object id) 
     { 
      T returnVal = Session.Get<T>(id); 
      return returnVal; 
     } 
     /// <summary> 
     /// Find Results by Name 
     /// </summary> 
     /// <typeparam name="T"></typeparam> 
     /// <param name="name"></param> 
     /// <returns></returns> 
     public T FindByName<T>(string name) 
      where T : class 
     { 
      var criteria = Session.CreateCriteria<T>(); 
      var targetEntity = typeof(T); 

      if (targetEntity == typeof(Article)) 
       criteria.Add(Restrictions.Eq("Title", name)); 
      else if (targetEntity == typeof(Category)) 
       criteria.Add(Restrictions.Eq("CatName", name)); 
      else if (targetEntity == typeof(News)) 
       criteria.Add(Restrictions.Eq("Title", name)); 
      else if (targetEntity == typeof(Video)) 
       criteria.Add(Restrictions.Eq("Title", name)); 
      else if (targetEntity == typeof(NewsCategory)) 
       criteria.Add(Restrictions.Eq("NewsCatName", name)); 
      else if (targetEntity == typeof(VideoCategory)) 
       criteria.Add(Restrictions.Eq("VideoCatName", name)); 
      else 
       criteria.Add(Restrictions.Eq("Name", name)); 


      return FindUnique<T>(criteria); 
     } 
     public T FindBySpecificColumn<T>(string colname, string findValue) 
      where T : class 
     { 
      var criteria = Session.CreateCriteria<T>(); 
      criteria.Add(Restrictions.Eq(colname, findValue)); 
      return FindUnique<T>(criteria); 
     } 
     public T FindBySpecificColumn<T>(string colname, int findValue) 
      where T : class 
     { 
      var criteria = Session.CreateCriteria<T>(); 
      criteria.Add(Restrictions.Eq(colname, findValue)); 
      return FindUnique<T>(criteria); 
     } 
     public IList<T> FindRandomBySpecificColumn<T>(string colname, int findValue) 
     where T : class 
     { 
      var criteria = Session.CreateCriteria<T>(); 
      criteria.Add(Restrictions.Eq(colname, Convert.ToBoolean(findValue))); 
      criteria.AddOrder(new RandomOrder()); 
      return Find<T>(criteria); 
     } 
     public IList<T> FindTopRecents<T>(int recCount, string colName) where T : class 
     { 
      return Session.CreateQuery(string.Format("from {0} order by {1} DESC", typeof(T), colName)) 
       .SetFirstResult(0) 
       .SetMaxResults(recCount) 
       .List<T>(); 


     } 
     /// <summary> 
     /// Returns a list of all instances of type T from the database. 
     /// </summary> 
     /// <typeparam name="T">The type of the given persistant instance.</typeparam> 
     public IList<T> GetAll<T>() 
      where T : class 
     { 
      IList<T> returnVal = Session.CreateCriteria<T>().List<T>(); 
      return returnVal; 
     } 
     /// <summary> 
     /// Returns a list of all instances of type T from the database for pagination 
     /// </summary> 
     /// <typeparam name="T">The type of the given persistant instance.</typeparam> 
     /// <param name="pageIndex">Number- page index.</param> 
     /// <param name="pageSize">Number - maximum page size.</param> 
     /// <returns>List of type the given persistent instance</returns> 
     public IList<T> GetAll<T>(int pageIndex, int pageSize) 
      where T : class 
     { 
      var criteria = Session.CreateCriteria(typeof(T)); 
      if (pageSize > 0) 
      { 
       criteria.SetMaxResults(pageSize); 
      } 
      return criteria.List<T>(); 
     } 
     /// <summary> 
     /// Find Unique values 
     /// </summary> 
     /// <typeparam name="T"></typeparam> 
     /// <param name="criteria"></param> 
     /// <returns></returns> 
     public T FindUnique<T>(ICriteria criteria) 
      where T : class 
     { 
      return (T)criteria.UniqueResult(); 
     } 
     /// <summary> 
     /// 
     /// </summary> 
     /// <typeparam name="T"></typeparam> 
     /// <param name="criteria"></param> 
     /// <returns></returns> 
     public IList<T> Find<T>(ICriteria criteria) where T : class 
     { 
      return criteria.List<T>(); 
     } 
     public IList<T> Find<T>(IEnumerable<string> strs) 
      where T : class 
     { 
      IList<ICriterion> objs = strs.Select(Expression.Sql).Cast<ICriterion>().ToList(); 
      var criteria = Session.CreateCriteria(typeof(T)); 
      foreach (var rest in objs) 
       criteria.SetFirstResult(0); 
      return criteria.List<T>(); 
     } 
     public IList<T> Find<T>(ICriteria criteria, PagingInfo paging) where T : class 
     { 
      paging.RowCount = Count(criteria); 

      if (paging.PageSize > 0) 
      { 
       criteria.SetMaxResults((int)paging.PageSize); 
       criteria.SetFirstResult((int)(paging.PageSize * paging.CurrentPage)); 
      } 

      return criteria.List<T>(); 
     } 
     protected int Count(ICriteria criteria) 
     { 
      //TODO check performance of this method (probably is better to use HQL with the COUNT(*) command) 
      return criteria.List().Count; 
     } 
     /// <summary> 
     /// 
     /// </summary> 
     /// <typeparam name="T"></typeparam> 
     /// <param name="query"></param> 
     /// <returns></returns> 
     public IList<T> GetListByQuery<T>(IQuery query) 
      where T : class 
     { 
      var list = query.List<T>(); 
      return list; 
     } 

     public ICriteria CreateCriteria<T>() where T : class 
     { 
      return Session.CreateCriteria(typeof(T)); 
     } 

     #endregion 
     #region IDisposable methods 
     public void Dispose() 
     { 
      if (Session != null) 
      { 
       if (Session.IsOpen) Session.Close(); 
      } 
     } 
     #endregion 
    } 

我們以下面的方式調用上面的類應用。

請提出是否需要更改Common repository類或需要實現其他某種模式。

在此先感謝!

+0

「用戶」表中有多少行? 「用戶」是否與其他實體建立關係?這些關係的「獲取模式」如何?您可以在「日誌」中看到多少SQL命令?這些SQL命令如何?... – Hailton 2012-07-18 06:19:43

+0

@ Hailton - 在NHProfiler中有大約12個SQL命令並且沒有警告。用戶表有超過15000條記錄。所有相關的實體都是lazy loading = false – 2012-07-18 09:40:51

+0

@Rick我認爲通過回答Hailton你指出了你的問題:'所有相關的實體都是lazy loading = false'。這是不好的做法。你應該使用延遲加載。你的方法FindBySpecificColumn返回完整的用戶實體和所有相關的實體。 – 2012-07-19 06:04:16

回答

1

有些事情要檢查:

  • 在您的映射 - 你渴望通過指定不lazyload
  • 檢查,看看產生證實上述
  • 的SQL加載整個用戶圖形是否有一個大量的用戶 - 你有一個索引
  • 如果你使用日誌工具,如log4net - 確保你沒有在調試模式或類似的日誌記錄NHibernate信息

它似乎也可能會創建一個會話工廠對每個請求(取決於如何存儲庫範圍),這是昂貴。您的會話工廠應該是一個單身人士,並且每個Web請求的會話都會在Web請求的生命週期範圍內進行。

配置應該在應用程序啓動時真正運行一次。

+0

瞭解所有以上幾點。但是爲什麼當應用程序和數據庫都在同一臺服務器上時,它的工作正常,爲什麼當應用程序和數據庫都在不同的服務器上時它很痛苦? – 2012-07-19 03:27:23

+0

然後應用程序和數據庫在不同的服務器上,這會增加延遲。這將在您的應用程序中顯示窗格點,例如app和db之間的很多小型往返行程。就像你的用戶存在的例子一樣。 – 2012-07-19 06:11:23

+0

因此,當不在同一個盒子上時,會出現額外的延遲/身份驗證問題。但是,如果您在每個請求中都創建會話工廠,那麼延遲時間會變得更加明顯。這很可能是你的問題。你有沒有使用Castle Windor這樣的IoC? – Chev 2012-07-19 07:05:18

相關問題