Nhibernate consuming a lot of memory

Asked

Viewed 79 times

1

I have an application that connects to the database via NHibernate, with this some operations are carried out as Save, Update e Delete. However, when performing these procedures, it is incredible how the memory accumulation is done by not automatically performing the memory dispensation with the GC not used by the CLR.

For example: A query that returns on average 1,000 Rows accumulates on average 100mb of memory, this is normal ?

The implementation of the base connection code is done as follows:

  public ISession OpenConnection<T>(SelectDb dbConfigKey, DatabaseType dbType)
    {
        ISessionFactory sessionFactory = null;

        try
        {
            switch (dbType)
            {
                #region Conexão com a base de dados SQL Server 2000
                case DatabaseType.SQLServer2000:
                    sessionFactory = Fluently.Configure()
                    .Database(MsSqlConfiguration.MsSql2000
                      .ConnectionString(dbConfigKey.ToDescriptionDatabase())
                                  .ShowSql()
                    )
                   .Mappings(m =>
                              m.FluentMappings
                                  .AddFromAssemblyOf<T>())
                    .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                    .Create(false, false))
                    .BuildSessionFactory();
                    break;
                #endregion

                #region Conexão com a base de dados SQL Server 2008
                case DatabaseType.SQLServer2008:
                    sessionFactory = Fluently.Configure()
                    .Database(MsSqlConfiguration.MsSql2008
                      .ConnectionString(dbConfigKey.ToDescriptionDatabase())
                                  .ShowSql()
                    )
                   .Mappings(m =>
                              m.FluentMappings
                                  .AddFromAssemblyOf<T>())
                    .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                    .Create(false, false))
                    .BuildSessionFactory();
                    break;
                #endregion

                #region Conexão com a base de dados PostgreSQL
                case DatabaseType.PostgreSQL:
                    sessionFactory = Fluently.Configure()
                    .Database(PostgreSQLConfiguration.Standard
                      .ConnectionString(dbConfigKey.ToDescriptionDatabase())
                                  .ShowSql()
                    )
                   .Mappings(m =>
                              m.FluentMappings
                                  .AddFromAssemblyOf<T>())
                    .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                    .Create(false, false))
                    .BuildSessionFactory();
                    break;
                #endregion

                #region Conexão com a base de dados MYSQL
                case DatabaseType.MYSQL:
                    sessionFactory = Fluently.Configure()
                    .Database(MySQLConfiguration.Standard
                      .ConnectionString(dbConfigKey.ToDescriptionDatabase())
                                  .ShowSql()
                    )
                   .Mappings(m =>
                              m.FluentMappings
                                  .AddFromAssemblyOf<T>())
                    .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                    .Create(false, false))
                    .BuildSessionFactory();
                    break;
                #endregion

                #region Conexão com a base de dados Oracle9
                case DatabaseType.Oracle9:
                    sessionFactory = Fluently.Configure()
                    .Database(OracleClientConfiguration.Oracle9
                      .ConnectionString(dbConfigKey.ToDescriptionDatabase())
                                  .ShowSql()
                    )
                   .Mappings(m =>
                              m.FluentMappings
                                  .AddFromAssemblyOf<T>())
                    .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                    .Create(false, false))
                    .BuildSessionFactory();
                    break;
                #endregion

                #region Conexão com a base de dados Oracle10
                case DatabaseType.Oracle10:
                    sessionFactory = Fluently.Configure()
                    .Database(OracleClientConfiguration.Oracle10
                      .ConnectionString(dbConfigKey.ToDescriptionDatabase())
                                  .ShowSql()
                    )
                   .Mappings(m =>
                              m.FluentMappings
                                  .AddFromAssemblyOf<T>())
                    .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                    .Create(false, false))
                    .BuildSessionFactory();
                    break;
                #endregion


            }


        }
        catch (Exception)
        {
            sessionFactory.Close();
            sessionFactory.Dispose();
        }
        return sessionFactory.OpenSession();
    }

where public Isession Openconnection(Selectdb dbConfigKey, Databasetype dbType) receives a class and passes the database configuration and connection type by parameter.

Any tips for using Nhibernate for that kind of purpose ?

1 answer

1

CLR does not do automatic cleaning in this case, so Dipose and Close.

Database connection frameworks "package" a whole complicated job of allocating memory on the server, making a connection to the database, etc. This whole job is done outside the . Net Runtime, why it is considered as a unmanaged resource.

Therefore, Garbage Collector is unaware of this unmanaged feature and cannot efficiently clean it (thinking that there is a way to clean this feature inside a finalizer of the object that packages it). Due to this it is very likely that you have problems with Leak memory.

The . Dispose() and the . Close() should stay inside the Finally block, as you are not closing the connection with the bank in cases where no exception occurs.

try {
...
}
catch (Exception)
{
...
}
finally {
    //Faz o tratamento caso o seu switch cair em default por algum motivo.
    if (sessionFactory != null) {
        sessionFactory.Close();
        sessionFactory.Dispose();
    }
}

About problems related to the performance of Nhibernante, I owe since I never worked with him.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.