Asp.net mvc 3 从EF转向Fluent NHibernate:内存泄漏、体系结构

Asp.net mvc 3 从EF转向Fluent NHibernate:内存泄漏、体系结构,asp.net-mvc-3,performance,nhibernate,jquery,fluent-nhibernate,Asp.net Mvc 3,Performance,Nhibernate,Jquery,Fluent Nhibernate,下午好,我正在将一个相当大的项目迁移到Fluent NHibernate以用于mono。我已经得到了大部分的关键功能运作良好,但我有一个内存问题 目前,该代码在我的两个控制器中。这一点似乎都不太理想。但我不知道该把这个放在哪里 private static ISessionFactory CreateSessionFactory() { return Fluently.Configure() .Database(MySQLConfiguration

下午好,我正在将一个相当大的项目迁移到Fluent NHibernate以用于mono。我已经得到了大部分的关键功能运作良好,但我有一个内存问题

目前,该代码在我的两个控制器中。这一点似乎都不太理想。但我不知道该把这个放在哪里

 private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
           .Database(MySQLConfiguration.Standard.ConnectionString(
           c => c.FromConnectionStringWithKey("DashboardModels")
       ))
   .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Accounts>())
   .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Notes>())
    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Sales_Forecast>())
     .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ChangeLog>())
      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Tasks>())

   .BuildSessionFactory();
    }
    ISessionFactory sessionFactory = CreateSessionFactory();
私有静态ISessionFactory CreateSessionFactory()
{
流畅地返回。Configure()
.Database(MySQLConfiguration.Standard.ConnectionString)(
c=>c.FromConnectionStringWithKey(“仪表板模型”)
))
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.BuildSessionFactory();
}
ISessionFactory sessionFactory=CreateSessionFactory();
我的大多数db调用都是AJAX,有几个同时启动。这让我相信我创建了太多的会话,这些会话没有被发布

  public ActionResult ReadAccounts([DataSourceRequest] DataSourceRequest request)
    {
        DataSourceResult result;

        using (var session = sessionFactory.OpenStatelessSession())
        using (var tx = session.BeginTransaction())
        {
            var customers = from customer in session.Query<Accounts>().AsNoTracking()
                            where !customer.Deleted
                            select customer;
            result = customers.ToDataSourceResult(request);
            tx.Commit();
        }
    return Json(result, JsonRequestBehavior.AllowGet);


    }
public ActionResult ReadAccounts([DataSourceRequest]DataSourceRequest请求)
{
数据源结果;
使用(var session=sessionFactory.openstatesession())
使用(var tx=session.BeginTransaction())
{
var customers=来自会话中的客户。Query().AsNoTracking()
哪里!customer.Deleted
选择客户;
结果=customers.ToDataSourceResult(请求);
tx.Commit();
}
返回Json(结果,JsonRequestBehavior.AllowGet);
}
假设我对只返回数据的方法使用无状态会话

  public JsonResult GetNoteInfo(int id = 0)
    {
        Notes note;
        using (var session = sessionFactory.OpenStatelessSession())
        using (var tx = session.BeginTransaction())
        {
             note = (from notes in session.Query<Notes>().AsNoTracking()
                        where notes.Note_ID == id
                        select notes).FirstOrDefault();
             tx.Commit();
            return Json(JsonResponseFactory.SuccessResponse(note), JsonRequestBehavior.DenyGet);
        }
    }
public JsonResult GetNoteInfo(int id=0)
{
附注;
使用(var session=sessionFactory.openstatesession())
使用(var tx=session.BeginTransaction())
{
note=(来自session.Query().AsNoTracking()中的notes)
其中notes.Note_ID==ID
选择notes).FirstOrDefault();
tx.Commit();
返回Json(JsonResponseFactory.SuccessResponse(注意),JsonRequestBehavior.DenyGet);
}
}
正如我提到的,这是可行的,但是我如何才能提高内存性能呢?大约有5种类似于底部方法的方法可以同时启动,因此,如果您能就如何防止内存快速扩展提出建议,我将非常感谢以前使用过这种方法的任何人。
谢谢你的时间和快乐的编码

将为每个请求实例化控制器。似乎每次创建控制器时都在调用CreateSessionFactory()。这是一个非常耗时的调用,在应用程序生命周期中通常只需执行一次。常用的方法是在Global.asax中处理此问题


至于会话,您已经使用语句将它们包装起来,这将确保它们关闭连接等,因此这部分在我看来是正确的。

这就是我个人解决问题的方式(在DotJoe、Oskar Berggren和本网站其他人的帮助下)

Global.asax.cs

public static ISessionFactory SessionFactory =
         SessionProvider.BuildSessionFactory();
控制器

public ActionResult ReadAccounts([DataSourceRequest] DataSourceRequest request)
{
    DataSourceResult result;

    using(ISession session = MvcApplication.SessionFactory.OpenSession())
    {
        using (ITransaction tx = session.BeginTransaction())
        {
            var customers = session.Query<Accounts>().Where(a => a.Deleted == false).AsNoTracking();
            //from customer in session.Query<Accounts>().AsNoTracking()
            //                where !customer.Deleted
            //                select customer;
            result = customers.ToDataSourceResult(request);
            tx.Commit();
        }
    }
    return Json(result, JsonRequestBehavior.AllowGet);
}
public ActionResult ReadAccounts([DataSourceRequest]DataSourceRequest请求)
{
数据源结果;
使用(ISession session=mvcapapplication.SessionFactory.OpenSession())
{
使用(ITransaction tx=session.BeginTransaction())
{
var customers=session.Query().Where(a=>a.Deleted==false).AsNoTracking();
//来自会话中的客户。Query().AsNoTracking()
//哪里!customer.Deleted
//选择客户;
结果=customers.ToDataSourceResult(请求);
tx.Commit();
}
}
返回Json(结果,JsonRequestBehavior.AllowGet);
}
然后,我在名为Utilities的文件夹中创建了一个类:

SessionFactory.cs

public class SessionProvider  
{
 public static ISessionFactory BuildSessionFactory()
 {
 return Fluently.Configure()
      .Database(MySQLConfiguration.Standard.ConnectionString(
      c => c.FromConnectionStringWithKey("DashboardModels")
  ))
 .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Accounts>())
 .BuildSessionFactory();

 }
}
公共类SessionProvider
{
公共静态ISessionFactory BuildSessionFactory()
{
流畅地返回。Configure()
.Database(MySQLConfiguration.Standard.ConnectionString)(
c=>c.FromConnectionStringWithKey(“仪表板模型”)
))
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.BuildSessionFactory();
}
}
我希望这段代码可以帮助其他需要在必要时从EF转换为NHibernate的人

这使得我在一个拥有145个用户的相当大的应用程序中的内存管理保持在450000KB多一点。(低于使用EF的600000KB)证明了NHibernate的可扩展性

我们也强烈推荐NHProf。它有很好的建议,并将为您的具体问题提供资源


如果你打算使用Mono,我认为这是一种方式。

很多假设,很少有事实。您认为您的会话为什么没有发布?你分析过你的应用程序吗?你是对的,迭戈,但是问题是如此明显,破坏了记忆,我只是想征求建议。如果我没有得到,那么分析将是我的第一个行动。谢谢你的建议,如果你能提供一个例子,那就太棒了。我几乎可以肯定你对sessionFactory的看法是正确的。你不应该在application_start中打开会话,如果你打开了,你应该再次关闭它。目前,您在那里有一个未分配的会话。我可以在应用程序端关闭它吗?您应该为每个请求打开一个新会话。除非您需要在应用程序启动期间从数据库加载一些配置设置或类似设置,否则您甚至不应该在应用程序启动中打开会话。噢,哇,我实际上是在为每个请求打开一个新会话。不知道我把它放进去的时候在想什么。谢谢你的提醒,我在NHProf上看到了一些随机会话,哈哈,就是这样