.NET Nhibernate会话使内存使用量增加

时间:2017-10-02 17:07:15

标签: c# asp.net-mvc nhibernate

我有一个使用Nhibernate连接多个informix数据库的.NET MVC webapi,我使用Repository和工作单元模式。

问题是当发送倍数请求到mvc web api,服务器内存增长并使iis mvc网站停止时。

这是工作单位:

public interface IUnitOfWorkNH: IDisposable
{
    void BeginTransaction();
    void Commit();
}

public class UnitOfWorkNH : IUnitOfWorkNH
{
    private ISessionFactory _sessionFactory;
    private ITransaction _transaction;

    public ISession Session { get; private set; }

    public UnitOfWorkNH(string connection)
    {
        string stringConnection = ConfigurationManager.AppSettings["NH_DSN"].ToString();
        if (!string.IsNullOrEmpty(connection))
        {
            stringConnection = connection;
        }
        _sessionFactory = Fluently.Configure()
            .Database(OdbcConfiguration.InformixODBC.ConnectionString(stringConnection)
            .Driver<NHibernate.Driver.OdbcDriver>()
            .Dialect<NHibernate.Dialect.InformixDialect>()
            //.ShowSql()
        )
            .Mappings(m =>
                      m.FluentMappings
                          .AddFromAssemblyOf<clsCiaMap>())
            .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                            .Create(false, false))

            .BuildSessionFactory();

        Session = _sessionFactory.OpenSession();   
    }        

    public void BeginTransaction()
    {
        _transaction = Session.BeginTransaction();
    }

    public void Commit()
    {
        try
        {
            // commit transaction if there is one active
            if (_transaction != null && _transaction.IsActive)
                _transaction.Commit();
        }
        catch
        {
            // rollback if there was an exception
            if (_transaction != null && _transaction.IsActive)
                _transaction.Rollback();

            throw;
        }
        finally
        {
            Session.Dispose();
        }
    }

    public void Rollback()
    {
        try
        {
            if (_transaction != null && _transaction.IsActive)
                _transaction.Rollback();
        }
        finally
        {
            Session.Dispose();
        }
    }

    public void Dispose()
    {
        if (this._transaction != null)
        {
            this._transaction.Dispose();
            this._transaction = null;
        }

        if (this.Session != null)
        {
            this.Session.Dispose();
            Session = null;
        }
        this._sessionFactory.Dispose();
        this._sessionFactory = null;
    }
}

这是Repository类:

public interface IRepository<T> where T : class
{
    List<T> GetAll();
    T GetById(int id);
    T GetById(string id);
    T GetById(T id);
    void Save(T entity);
    void Delete(T entity);
}

public  class RepositoryNH<T> : IRepository<T> where T : class
{
    ISession _session;


    public RepositoryNH(ISession session)
    {
        _session = session;
    }

    public ISession Session { get { return _session; } }

    public List<T> GetAll()
    {
        return Session.QueryOver<T>().List().ToList();
    }

    public T GetById(int id)
    {
        return _session.Get<T>(id);
    }

    public T GetById(string id)
    {
        return Session.Get<T>(id);
    }

    public T GetById(T id)
    {
        return _session.Get<T>(id);
    }

    public void Save(T entity)
    {
        Session.SaveOrUpdate(entity);
        Session.Flush();
    }

    public void Delete(T entity)
    {
        Session.Delete(entity);
    }
}

我不知道在这些课程中是否有错,我需要帮助。

1 个答案:

答案 0 :(得分:0)

您正在SessionFactory类的构造函数中创建新的UnitOfWorkNH。这表明一次会有多个会话工厂实例。由于这些会话工厂的所有实例都被加载到内存中而从未被丢弃,因此内存使用量不断增加。

另外,建立会话工厂是昂贵的电话。反复创建新的会话工厂将严重影响性能。

理想情况下,您的会话工厂应该是单身人士。它应该在应用程序启动时构建(通过调用BuildSessionFactory()方法)。然后,应使用相同的会话工厂实例使用ISession语句创建_sessionFactory.OpenSession()个实例。

以下是一些原始代码; 不完全是单身,但可能会有所帮助。我仍然建议你考虑使用单身人士。

internal static class NHSessionFactory
{
    static Configuration nhConfiguration;
    static ISessionFactory nhSessionFactory;
    const FlushMode defaultFlushMode = FlushMode.Commit;

    internal static ISessionFactory SessionFactory
    {
        get { return nhSessionFactory; }
    }

    internal static void CreateSessionFactory()
    {
        CreateSessionFactory(null);
    }
    internal static void CreateSessionFactory(string configFilePath)
    {
        CreateSessionFactory(configFilePath, defaultFlushMode);
    }
    internal static void CreateSessionFactory(string configFilePath, FlushMode flushMode = defaultFlushMode)
    {
        if(nhSessionFactory != null)
            throw new InvalidOperationNHFacadeException("SessionFactory is already created.");

        nhConfiguration = new Configuration();
        try
        {
            if(string.IsNullOrEmpty(configFilePath))
                nhConfiguration.Configure();
            else
                nhConfiguration.Configure(configFilePath);

            nhConfiguration.SessionFactory().DefaultFlushMode(flushMode);
        }
        catch(Exception exception)
        {
            throw new NHFacadeException("Failed to configure session factory.", exception);
        }
        try
        {
            nhSessionFactory = nhConfiguration.BuildSessionFactory();
        }
        catch(Exception exception)
        {
            throw new NHFacadeException("Failed to build session factory.", exception);
        }
    }

    internal static void CloseSessionFactory()
    {
        if(nhSessionFactory != null)
        {
            if(nhSessionFactory.IsClosed == false)
                nhSessionFactory.Close();
            nhSessionFactory.Dispose();
            nhSessionFactory = null;
        }

        if(nhConfiguration != null)
            nhConfiguration = null;
    }
}

请注意,在上面的代码中,方法CreateSessionFactory()验证了对自身的冗余调用。您需要做的就是在应用程序启动时调用CreateSessionFactory()并在应用程序退出时调用CloseSessionFactory()