1

下午好,我正在将一个相当大的项目迁移到 Fluent NHibernate 以用于单声道。我已经让大部分关键功能运行良好,但是我遇到了内存问题。

目前,此代码在我的两个控制器中。这似乎甚至不是最佳的。但我不确定把这个放在哪里。

 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();

我的大多数数据库调用都是 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);


    }

考虑到我将 StatelessSessions 用于仅返回数据的方法。

  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);
        }
    }

正如我所提到的,这是可行的,但是如何提高内存性能呢?大约有 5 种与底部方法类似的方法同时触发,因此如果您之前做过此操作的任何人,请告知如何防止内存快速膨胀,我将不胜感激。感谢您的时间和愉快的编码!

4

2 回答 2

3

控制器将为每个请求实例化。看起来您可能会在每次创建控制器时调用 CreateSessionFactory()。这是一个非常耗时的调用,通常应该在应用程序生命周期内只执行一次。一种常见的方法是在 Global.asax 中处理这个问题。

至于会话,您已将它们包装在 using 语句中,这将确保它们关闭连接等,因此这部分对我来说是正确的。

于 2013-01-31T07:42:52.757 回答
0

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

全球.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);
}

然后我在一个名为 Utilities 的文件夹中创建了一个类:

会话工厂.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();

 }
}

我希望这段代码可以帮助其他需要从 EF 转换为 NHibernate 的人。

这使我的内存管理在一个拥有 145 个用户的相当大的应用程序中保持在略高于 450,000kb 的范围内。(从使用 EF 的 600,000kb 减少)证明了 NHibernate 的可扩展性。

强烈推荐NHProf。它有很好的建议,并将为您的特定问题提供资源。

如果您要使用 Mono,我认为这是要走的路。

于 2013-01-31T21:37:34.913 回答