簡體   English   中英

流利的NHibernate的內存泄漏

[英]Memory Leak in Fluent NHibernate

我正在使用Fluent NHibernate作為我們的ORM,並且遇到內存泄漏錯誤。

我在任務管理器中觀察到,每當我嘗試從同一台PC上的不同Web瀏覽器訪問主頁時,CPU使用率為2-3%,但是內存使用率為80-90%,這會導致網站變慢並導致系統掛起。 要再次運行我的網站,我必須從任務管理器中結束該過程。 還有一件事,當我從瀏覽器訪問它時會占用一些內存,但是當我關閉它時,它不會釋放所有資源(該內存)。

我以這種方式制作了網站的架構:-

  1. 我做了一個“ ParentObject”類,在其中我創建了一個靜態對象作為Repository對象。
  2. 我創建的所有實體都繼承自“ ParentObject”類。
  3. 我又做了一個繼承自“ Controller”類的BaseController類,在Base類中我使用了以下代碼:

     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類的所有控制器。 這樣,每次操作命中我都會得到“ _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();
    }    
 }

注意:我們尚未在存儲庫中關閉Session,這是因為我使用的是惰性初始化,也曾在Views中使用過它,因此如果我在此處關閉Session,則會收到顯示“找不到Session”的錯誤消息。

這就是我如何瀏覽網站的方法。 您能否查看一下此代碼,並讓我知道為什么會收到此錯誤。

預先感謝您。

問題:

  • 您基本上每個實體永遠都只能舉行一個會話。 但是,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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM