NHibernate StructureMap ASP.NET веб-формы System.OutOfMemoryException - PullRequest
2 голосов
/ 15 января 2011

я создал веб-приложение, используя веб-форму Asp.NET, NHibernate для доступа к базе данных Sql Server 2008 и StructureMap в качестве контейнера IOC.

Кажется, все работает нормально, так как немногие пользователи используют его; когда число пользователей увеличивается (можно сказать, 10+ пользователей), веб-приложение вылетает с этой ошибкой:

System.OutOfMemoryException

Я скачал пакет redgate ants: инструмент производительности сообщает, что максимальное время процессора в 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;
}
}

Так я читаю данные из базы данных:

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 ]

2 голосов
/ 15 января 2011

Похоже, что SessionFactory создается при каждом вызове метода GetAll. Создание SessionFactory - дорогостоящая операция. Я бы выбрал один из двух вариантов ниже

Создайте SessionFactory в методе запуска приложения. Это будет в файле Global.asax.cs. Затем предоставьте статическое открытое свойство для SessionFactory в классе Global asax, к которому можно получить доступ из любого метода, например:

Global.SessionFactory.OpenSession

Другой вариант - иметь фабрику репозитория или класс провайдера репозитория. Это будет иметь конструктор, который будет принимать в строке подключения. Он создаст 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 голос
/ 15 января 2011

Прежде всего вы создаете новую фабрику сессий для каждого вызова.Это дорогая операция.У вас должна быть одна фабрика сеансов для вашего приложения, которая создает сеансы по мере необходимости.Во-вторых, вы не следуете схеме работы, рекомендованной NHibernate:

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

...