Configurando o NHibernate por código

Olá pessoal. Aqui temos a necessidade de flexibilizar a string de conexão do sistema, de tal forma que o usuário possa mudá-la a partir  de uma tela de configurações. Outro detalhe que prevemos, é a mudança de banco de dados sem a necessidade de recompilar o projeto. Levando tudo isso em consideração, mais a possibilidade de adicionar algum parâmetro de execução e habilitar ou não a exibição de SQL ou geração de estatísticas, resolver configurar o NHibernate por código. Contudo o desafio em fazer isso estava no fato de que utilizamos o projeto uNHaddins.

Até o momento estávamos utilizando a classe DefaultSessionFactoryConfigurationProvider(),  responsável por carregar e configurar o NHibernate. A solução foi criar uma classe herdada de AbstractConfigurationProvider. Essa classe abstrata expoem os métodos necessários que devem ser implementados para que possam ter uma inicialização personalizada do NHibernate. Sendo assim temos a seguinte classe:

/// <summary>
    /// Esta classe configura manualmente, por código, as propriedades do NHibernate.
    /// Estamos fazendo por código para facilitar a troca de connection string e até mesmo
    /// a troca de banco de dados.
    /// </summary>
    public class ByCodeConfigurationProvider: AbstractConfigurationProvider
    {
        private readonly string _connectionString;
        private Configuration _configuration;

        /// <summary>
        /// Construtor da classe. Recebe como parâmetro <paramref name="connectionString"/>
        /// </summary>
        /// <param name="connectionString">String de conexão do banco de dados em uso</param>
        public ByCodeConfigurationProvider(string connectionString)
        {
            _connectionString = connectionString;
        }

        private void ConfigureByCode()
        {
            if (_configuration == null)
            {
                _configuration =  new Configuration();
                _configuration.SetProperty("connection.driver_class","NHibernate.Driver.SqlClientDriver");
                _configuration.SetProperty("hbm2ddl.auto","update");
                _configuration.SetProperty("show_sql","true");
                _configuration.SetProperty("connection.connection_string",@"Data Source=SRV2003NET\SQLEXPRESS;Initial Catalog=NotasBD;Persist Security Info=True;User ID=NotasMaster;Password=cont10rol");
                _configuration.SetProperty("adonet.batch_size","10");
                _configuration.SetProperty("dialect","NHibernate.Dialect.MsSql2005Dialect");
                _configuration.SetProperty("use_outer_join","true");
                _configuration.SetProperty("command_timeout","10");
                _configuration.SetProperty("query.substitutions","true 1, false 0, yes 'Y', no 'N'");
                _configuration.SetProperty("current_session_context_class","uNhAddIns.SessionEasier.Conversations.ThreadLocalConversationalSessionContext, uNhAddIns");
                _configuration.SetProperty("proxyfactory.factory_class","NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
                _configuration.SetProperty("use_proxy_validator","false");
                _configuration.AddAssembly(Assembly.GetAssembly(typeof (Pessoa)));
                
                var eventos =   _configuration.EventListeners;
                eventos.PreUpdateEventListeners = new List<IPreUpdateEventListener>(eventos.PreUpdateEventListeners){new EventListener()}.ToArray();
                eventos.PreInsertEventListeners = new List<IPreInsertEventListener>(eventos.PreInsertEventListeners){new EventListener()}.ToArray();
            }

        }


        public override IEnumerable<Configuration> Configure()
        {
            ConfigureByCode();
            return new SingletonEnumerable<NHibernate.Cfg.Configuration>(_configuration);
        }
    }

Como pode ser visto, o método ConfigureByCode instancia um objeto Configuration do NHibernate e utilizando o método SetProperty, configura suas propriedades. O construtor da classe recebe como parâmetro uma string que contém a connection string do banco, porém não estamos utilizando nesse momento. Mas o detalhe da flexibilização é que  como estamos fazendo tudo por código, é muito fácil ler algum arquivo de configuração e mudar essas propriedades como desejarmos, sem termos que recompilar código.

Aqui centralizamos a carga de nossos serviços em uma classe tipo ServiceLocator, e nela executamos a carga do NHibernate assim:

 

public class ServiceLocatorProvider
   {
       public static void Initialize()
       {
           var container = new WindsorContainer();
           container.AddFacility<PersistenceConversationFacility>();

           var nhConfigurator = new ByCodeConfigurationProvider("");

           var sfp = new SessionFactoryProvider(nhConfigurator);

           container.Register(Component.For<ISessionFactoryProvider>().Instance(sfp));
           container.Register(Component.For<ISessionWrapper>().ImplementedBy<SessionWrapper>());
           container.Register(Component.For<IConversationFactory>().ImplementedBy<DefaultConversationFactory>());
           container.Register(Component.For<IConversationsContainerAccessor>().ImplementedBy<NhConversationsContainerAccessor>());
           container.Register(Component.For<ISessionFactory>().Instance(sfp.GetFactory(null)));

           container.Register(Component.For(typeof(IDao<>)).ImplementedBy(typeof(BaseDao<>)).LifeStyle.Transient);
     var sl = new WindsorServiceLocator(container);
     container.Register(Component.For<IServiceLocator>().Instance(sl));
     ServiceLocator.SetLocatorProvider(() => sl);
  }
}

 

Segue aí a dica!

Esse post foi publicado em NHibernate. Bookmark o link permanente.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s