2013-03-09 61 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