开发者

NHibernate StructureMap ASP.NET webform System.OutOfMemoryException

i created a web application by using Asp.NET webform, NHibernate to access Sql Server 2008 database and StructureMap as IOC Container.

Everything seem to work ok since few users use it; when user number increases (we can say 10+ users) webapp crashes with this error:

System.OutOfMemoryException

I downloaded redgate ants suite: the performance tool says that maximum cpu time is in NHibernate createSessionFactory for a GetAll request.

This is my NHibernateHelper object:

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
        .ConnectionSt开发者_如何学JAVAring
        (
            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;
}
}

This is the way i read data from 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;
    }
}

Am i doing any mistakes? Could it be the one which provokes OutOfMemoryException? Best regards


It looks like the SessionFactory is created in every call to the GetAll method. Creating the SessionFactory is an expensive operation. I would follow one of the two options below

Create the SessionFactory in the Application's start method. This would be in the Global.asax.cs file. Then expose a static public property for the SessionFactory in the Global asax class that could be accessed from any method as so

Global.SessionFactory.OpenSession

The other option would be to have a Repository factory or a Repository Provider class. This would have a constructor that would take in the connection string. It will build the SessionFactory based on the constructor parameters and create an instance of Repository class. The Repository class would have all your Getxxx methods. So this would be something like

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

And you can configure StructureMap to provide instances of RepositoryFactory

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

Now you can tell SM to give you instance of RepositoryFactory using which you can obtain a Repository instance and make all the Getxx calls.

Hope this helps!


First of all you're creating a new Session factory for every call. This is an expensive operation. You should have one session factory for your app that creates sessions as needed. Second of all you're not following the unit of work pattern that is recommended by NHibernate:

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜