2013-03-09 49 views
1

我使用Fluent NHibernate作爲我們的ORM,並且出現內存泄漏錯誤。Fluent NHibernate中的內存泄漏

我在任務管理器中觀察到它,無論何時我試圖從同一臺PC上的不同web瀏覽器訪問主頁,CPU使用率爲2-3%,但內存使用率爲80-90%,導致網站並導致系統掛起。 並再次運行我的webisite,我必須結束從任務管理器的過程。還有一件事,當我從瀏覽器訪問它時會使用一些內存,但是當我關閉它時,它不會釋放所有資源(即內存)。

我已經作出了網站的架構是這樣的: -

  1. 我已經在我所創建的Repository對象爲靜態成員的類「ParentObject」。
  2. 我創建的所有實體都已從「ParentObject」類繼承。
  3. 我已經我從「控制器」類繼承,並在基類中我已經使用這個代碼多了一個類BaseController: -

    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
        base.OnActionExecuting(filterContext); 
        EdustructRepository Repository; // My Repository Class where I have written logic for opening and closing Save and Update Session.I have mentioned my this logic below 
        if (Session["Repository"] != null) 
        { 
         Repository = (EdustructRepository)Session["Repository"]; 
         if (!Repository.GetSession().Transaction.IsActive) 
          Repository.GetSession().Clear(); 
        } 
        else 
        { 
         Repository = new EdustructRepository(typeof(ActivityType), FluentNhibernateRepository.DataBaseTypes.MySql); 
         Session["Repository"] = Repository; 
        } 
        if (ParentObject._repository == null) 
        { 
         ParentObject._repository = new EdustructRepository(); // Here i have set the ParentObject's static variable "_repository" by this i have accessed repository in all my Entities . 
        } 
    } 
    
  4. 我繼承了我所有的控制器BaseController類。通過這個,我得到了每個Action命中的「_repository」對象。

我的會話管理邏輯

public class EdustructRepository : NHibernetRepository 
{ 

    public void Save<T>(T item, bool clearSession) 
    { 
     if (typeof(T).GetProperty("Created_at").GetValue(item, null).ToString() == DateTime.MinValue.ToString()) 
     { 
      typeof(T).GetProperty("Created_at").SetValue(item, MySqlDateTime.CurrentDateTime(), null); 
     } 
     typeof(T).GetProperty("Updated_at").SetValue(item, MySqlDateTime.CurrentDateTime(), null); 
     base.CheckAndOpenSession(); 
     using (var transaction = base.GetSession().BeginTransaction()) 
     { 
      try 
      { 
       base.GetSession().SaveOrUpdate(item); 
       transaction.Commit(); 
       if (clearSession) 
       { 
        Session.Clear(); 
       } 
      } 
      catch 
      { 
       base.Evict(item); 
       base.Clear(); 
       throw; 
      } 
     } 
     //base.Save<T>(item, clearSession); 
    } 

    public void Save<T>(T item) 
    { 
     Save<T>(item, false); 
    } 
} 

public class NHibernetRepository : IDisposable 
{ 
    public static ISessionFactory _SessionFactory = null; 

    protected ISession Session = null; 

    private ISessionFactory CreateSessionFactory() 
    { 
     return Fluently.Configure() 
      .Database(MySQLConfiguration.Standard.ConnectionString(c => c.FromConnectionStringWithKey("DBConnectionString"))) 
      .Mappings(m =>m.FluentMappings.AddFromAssembly((Assembly.Load("Edustruct.Social.DataModel"))).Conventions.Add<CascadeConvention>()) 
      .ExposeConfiguration(cfg => cfg.SetProperty(NHibernate.Cfg.Environment.CurrentSessionContextClass,"web")) 
      .BuildSessionFactory(); 
    } 

    protected void CheckAndOpenSession() 
    { 
     if (_SessionFactory == null) 
     { 
      _SessionFactory = CreateSessionFactory(); 
     } 
     if (Session == null) 
     { 
      Session = _SessionFactory.OpenSession(); 
      Session.FlushMode = FlushMode.Auto; 
     } 
     if (!Session.IsOpen) 
      Session = _SessionFactory.OpenSession(); 
     else if (!Session.IsConnected) 
      Session.Reconnect(); 
    }  
} 

注:我們沒有在我們的倉庫閉門會議是因爲我使用延遲初始化也是我在視圖中使用它,所以如果我在這裏結束會議我收到一個顯示「未找到會話」的錯誤。

這就是我如何使我的網站流動。 請您查看這段代碼,讓我知道爲什麼我得到這個錯誤。

感謝您提前。

回答

1

問題:

  • 你basicly持有每個實體永遠開一個會議。然而,ISession實現了不適用於此的工作單元模式。
  • CheckAndOpenSession()不是線程安全的,但web服務本質上是線程化的:每個請求通常都有自己的線程。
  • 什麼用

每個經營都應該有在它的最終處置自己的會話。業務操作通常是控制器操作或Web方法。

樣品

// on appstart 
GlobalSessionFactory = CreateSessionFactory(); 


// in basecontroller befor action 
protected override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    base.OnActionExecuting(filterContext); 
    DatabaseSession = GlobalSessionFactory.OpenSession(); 
} 

// in basecontroller after action (pseudocode) 
protected override void OnActionExecuted() 
{ 
    DatabaseSession.Dispose(); 
} 
+0

FIRO嗨, thanx您的回覆,我不能關閉會話這裏 保護覆蓋無效OnActionExecuted() { 的DatabaseSession。處置(); } 因爲我正在使用延遲初始化,並且這將利用視圖上的會話對象,因爲我也對視圖進行了編碼。並且上述事件將在視圖呈現之前調用。所以,如果我在這裏關閉它,它會給出一個錯誤「未找到會話」。 – Tarun 2013-03-12 15:02:53

+0

海事組織你應該修正「我在視圖中使用代碼」,因爲它會導致隱藏的SELECT N + 1殺死生產性能。在動作中使用預先獲取/獲取路徑以減輕在視圖中對開放會話的需求:更容易推理,單元測試,理解 – Firo 2013-03-13 06:54:41