NHibernate StructureMap ASP.NET webform System.OutOfMemoryException

时间:2011-01-15 19:20:46

标签: asp.net nhibernate fluent-nhibernate structuremap

我使用Asp.NET webform创建了一个Web应用程序,NHibernate以IOC Container的身份访问Sql Server 2008数据库和StructureMap。

由于很少有用户使用它,所以似乎一切正常;当用户数量增加时(我们可以说超过10个用户)webapp因此错误而崩溃:

的System.OutOfMemoryException

我下载了redgate ants套件:性能工具说最大的cpu时间在NHibernate createSessionFactory中,用于GetAll请求。

这是我的NHibernateHelper对象:

public static NHibernate.ISessionFactory _sessionFactory;
public static NHibernate.ISessionFactory createSessionFactory()
{
try
{
    if (_sessionFactory == null)
    {
    return
        FluentNHibernate.Cfg.Fluently.Configure()
        .Database
        (
        FluentNHibernate
        .Cfg.Db.MsSqlConfiguration.MsSql2008
        .ConnectionString
        (
            c => c
            .Server(ConfigurationManager.DbConnectionValue.Server)
            .Username(ConfigurationManager.DbConnectionValue.User)
            .Password(ConfigurationManager.DbConnectionValue.Password)
            .Database(ConfigurationManager.DbConnectionValue.Database)
        )
        .ProxyFactoryFactory("NHibernate.ByteCode.LinFu.ProxyFactoryFactory,NHibernate.ByteCode.LinFu")
        )
        .Mappings
        (
        m => m.FluentMappings.AddFromAssemblyOf<Repository.IRepositoryBlocco>()
        )

        .BuildSessionFactory();
    }
    else
    return _sessionFactory;
}
catch (Exception ex)
{
    throw ex;
}
}

这是我从db中读取数据的方式:

public IList<DomainModel.Model.Variabile> GetAll()
{
    try
    {
    var session_factory = NHibernateHelper.createSessionFactory();

    using (var session = session_factory.OpenSession())
    {
        using (var transaction = session.BeginTransaction())
        {
        var query = session.Linq<DomainModel.Model.Variabile>()
            .OrderBy(v => v.ordine);

        return query.ToList();
        }
    }
    }
    catch (Exception ex)
    {
    throw ex;
    }
}

我有任何错误吗?是否会引发OutOfMemoryException? 最好的问候

2 个答案:

答案 0 :(得分:2)

看起来每次调用GetAll方法时都会创建SessionFactory。创建SessionFactory是一项昂贵的操作。我会按照以下两个选项之一

在Application的start方法中创建SessionFactory。这将在Global.asax.cs文件中。然后在Global asax类中公开SessionFactory的静态公共属性,可以从任何方法访问它,如下所示

Global.SessionFactory.OpenSession

另一种选择是拥有Repository工厂或Repository Provider类。这将有一个构造函数,它将接受连接字符串。它将基于构造函数参数构建SessionFactory并创建Repository类的实例。 Repository类将拥有所有Getxxx方法。所以这就像

public interface IRepositoryFactory
{
   IRepository GetRepository();
}

public interface IRepository:IDispose
{
   IEnumerable<T> Getxxx<T>();

}

public class RepositoryFactory:IRepositoryFactory
{
    private string _connectionString;
    public RepositoryFactory(string connectionString)
    {
            _connectionString=connectionString;
    }

    public IRepository GetRepository()
    {
       //use the connection string and fluently build SessionFactory
       return new Repository(SessionFactory.OpenSession());
    }     
}

public class Repository:IRepository
{
   private ISession _session;
   public Repository(ISession session)
   {
        _session=session;
   }

   public IEnumerable<T> Getxxx<T>()
   {
       return _session.Query<T>();
   }

   public void Dispose()
   {
     //dispose session and any other disposables
   }
}

您可以配置StructureMap以提供RepositoryFactory

的实例
For<IRepositoryFactory>.Use<RepositoryFactory>().Ctor<string>.EqualToAppSetting("connStr");

现在,您可以告诉SM为您提供RepositoryFactory实例,您可以使用该实例获取Repository实例并进行所有Getxx调用。

希望这有帮助!

答案 1 :(得分:1)

首先,您要为每次通话创建一个新的Session工厂。这是一项昂贵的操作。您的应用程序应该有一个会话工厂,可以根据需要创建会话。其次,你没有遵循NHibernate推荐的工作单元模式:

http://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.aspx