Olá pessoal, depois de um tempo parado, vamos falar um pouco de NHibernate. Este post estava pronto a bastante tempo pode ser que alguma coisa não seja mais aplicado nas novas versão do NHibernate.
Instalando
A forma mais simples de instalar o NHibernate é usando o NuGet, abaixo o comando para instalar o NHibernate. No exemplo estou usando a versão 3.3.3.4000 para o .NET Framework 4.0.
1
install-package NHibernate
Configurando
Adicione um arquivo XML na solução chamado hibernate.cfg.xml. Este arquivo irá conter as especificações de conexão a base de dados e outras configurações da conexão. Abaixo segue uma configuração padrão para o banco MySQL e uma aplicação Web:
Alguns pontos importantes ao notar o domínio é a presença do modificador virtual nos métodos e propriedades, este modificador possibilita o NHibernate criar um proxy sobre a nossa classe e que não existe nenhuma presença de infraestrutura de acesso a dados.
Mapeamento
O mapeamento abaixo esta escrito em XML, existem outras formas de mapeamento como por exemplo atributos ou por código usando NHibernate Fluent. Uma vantagens que eu vejo ao usar XML é que você não precisa recompilar a aplicação para alterar alguma regra no mapeamento e a forma de utilização ao meu ver é mais simples e didática.
Abaixo esta o mapeamento da nossa classe de domínio acima.
Uma das configurações mais importantes deste mapeamento é o gerador da chave primária, neste exemplo estou usando hilo, ele é usado para gerar a chave sem precisar ir até a base de dados não quebramos a Unit Of Work.
Click no elemento abaixo para maiores detalhes de seus atributos.
A Session Factory é responsável por construir as sessões. Quando uma aplicação é iniciada deve-se carregar todas as configurações do NHibernate e mapeamentos para criar a Session Factory, a criação da Session Factory é um processo demorado e deve ser feito apenas uma vez na aplicação. O código abaixo é uma implementação do padrão Singleton e garante que a Session Factory será criada apenas uma vez na aplicação.
privatereadonly ISessionFactory _sessionFactory; public ISessionFactory CurrentSessionFactory { get { return _sessionFactory; } }
privatestaticvolatile SessionFactoryFactory _instance; privatestaticreadonlyobject SyncRoot = new Object();
privateSessionFactoryFactory() { var cfg = new Configuration(); cfg.Configure(); cfg.AddAssembly(typeof(SessionFactoryFactory).Assembly);
_sessionFactory = cfg.BuildSessionFactory(); }
publicstatic SessionFactoryFactory Instance { get { if (_instance == null) { lock (SyncRoot) { if (_instance == null) _instance = new SessionFactoryFactory(); } }
return _instance; } } }
Action Filter - Transaction Per Request
Exitem várias formas de criar uma session em uma aplicação web a forma que irei adotar é bem comum, ela cria uma session por cada requisição feita.
Simplesmente vamos criar um action filter que irá interceptar a “entrada” e a “saída” da nossa action da controller.
Na entrada vamos pegar a session usando o contêiner de dependência e iniciar uma transação setando o nível de isolamento da mesma. Lista dos níveis de isolamentos.
Na saída vamos verificar se houve um erro na requisição. Caso não houve um erro a transação será feito um commit da transação, senão será feito um rollback na mesma.
Este actino filter será utilizado para poder acoplar e desacoplar a session do NHibernate no contexto atual, para ficar mais simples a utilização vamos registrar ele no global filter assim não precisamos decorar a nossa action com esta anotação.
publicoverridevoidOnActionExecuting(ActionExecutingContext filterContext) { if (!CurrentSessionContext.HasBind(SessionFactoryFactory.Instance.CurrentSessionFactory)) { CurrentSessionContext.Bind(IoCContainer.Get<ISession>()); } }
publicoverridevoidOnActionExecuted(ActionExecutedContext filterContext) { var currentSession = CurrentSessionContext.Unbind(SessionFactoryFactory.Instance.CurrentSessionFactory); if (currentSession == null) return; currentSession.Close(); currentSession.Dispose(); } }
Controller
Notem que estou recebendo a session no construtor da controller, quem irá fornecer esta session será o contêiner de dependência. A action create do método post esta decorada com a anotação TransactionPerRequest, isto indica que esta action terá um controle de transação.
[HttpGet] public ActionResult Create() { return View(); }
[HttpPost] [TransactionPerRequest] public ActionResult Create(CreateViewModel viewModel) { if (!ModelState.IsValid) return Error("Existem campos para preencher.", View(viewModel));
var account = new Account(viewModel.Email, viewModel.Password); _session.Save(account);
return Information("Sua conta foi criada com sucesso.", RedirectToAction("Index", "Home")); } }
Existem várias formas de buscar dados usando NHibernate segue alguns abaixo: