Este artigo mostra como usar o Fluent NHibernate e o NHibernate 4.0 para criar uma aplicação que realiza o login e faz o registro de um novo usuário no banco de dados PostgreSQL, mostrando também como realizar as operações CRUD de manutenção dos usuários usando o padrão Repository.
Se você já chegou a usar o NHibernate (para saber como usar os recursos do NHibernate, acesse esta seção), mas não conhece o Fluent NHibernate, deve saber que gerar os arquivos de mapeamento (.hbm) dá muito trabalho e que é uma tarefa que está sujeita a erros. Pois se esse era um quesito que o desmotivava a usá-lo, fique sabendo que agora você não tem mais essa desculpa!
O Fluent NHibernate chegou (há um bom tempo, por sinal) para auxiliar a realização dos mapeamentos das suas entidades com o seu banco de dados. Com ele podemos realizar o mapeamento via código sem ter que usar os arquivos .hbm.
Apenas para comparar, veja abaixo um exemplo de um arquivo de mapeamento .hbm gerado e sua contrapartida usando o Fluent NHibernate:
(fonte: https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started)
Arquivo XML .hbm
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="QuickStart" assembly="QuickStart"> <class name="Cat" table="Cat"> <id name="Id"> <generator class="identity" /> </id> <property name="Name"> <column name="Name" length="16" not-null="true" /> </property> <property name="Sex" /> <many-to-one name="Mate" /> <bag name="Kittens"> <key column="mother_id" /> <one-to-many class="Cat" /> </bag> </class> </hibernate-mapping>
Código Fluent NHibernate equivalente
public class CatMap : ClassMap<Cat> { public CatMap() { Id(x => x.Id); Map(x => x.Name) .Length(16) .Not.Nullable(); Map(x => x.Sex); References(x => x.Mate); HasMany(x => x.Kittens); } }
O Fluent NHibernate pode ser baixado no seguinte link: http://www.fluentnhibernate.org/
Neste artigo, eu vou criar um projeto Windows Forms usando a linguagem VB.NET e usando o NHibernate e Fluent NHibernate criar um formulário de login e registro de usuários para acessar um banco de dados PostgreSQL.
Recursos usados
- Visual Studio 2013 Express for windows desktop
- Linguagem C#
- NHibernate 4.0
- Fluent NHibernate
- Provedor Npgsql para conexão com o PostGreSQL
- PostgreSQL 9.3
Objetivos
- Usar os recursos do NHibernate e Fluent NHibernate e criar um formulário de Login em uma aplicação Windows Forms para acessar o PostgreSQL
Aprendizado
- Criar uma aplicação Windows Forms usando a linguagem VB .NET
- Criar um banco de dados e tabela no PostgreSQL
- Criar um repositório para acesso a dados
- Criar as entidades para realizar o mapeamento ORM
- Realizar o mapeamento ORM usando o Fluent NHibernate
- Realizar o CRUD no PostgreSQL usando o NHibernate
Criando o banco de dados e a tabela no PosgreSQL
Para criar o banco de dados e a tabela, vamos usar o pgAdmin III (deve ser compatível com a versão do PostgreSQL que você usar).
Quando você abrir o pgAdmin verá seguinte janela:
Na janela à esquerda, temos as conexões com o servidor de banco de dados. Inicialmente temos uma conexão padrão.
Durante a instalação, o PostGreSQL já configurou o acesso ao nosso servidor local. Clique duas vezes sobre o item PostGreSQL 9.3 (localhost:5432) para abrir a janela de conexão como servidor e informar a senha que você definiu durante a instalação para acessar o PostgreSQL.
Se você clicar em (+) da opção Databases, verá que já existe um banco de dados definido como Postgresql que foi criado automaticamente na instalação. Esse banco de dados não será utilizado e não pode ser excluído por se tratar de um banco utilizado para administração do Postgresql.
Vamos criar nosso banco de dados. Clique com o botão direito do rato em cima de Databases e escolha a opção New Database:
Na janela New DataBase informe o nome do banco de dados – Cadastro e define o Owner como sendo o usuário postgres:
Agora vamos criar a nossa tabela usuários. Para isso, faça o seguinte:
- Selecione o objeto Tables()
- Clique no menu SQL
- Na janela do editor SQL digite a instrução SQL Create Table conforme abaixo para criar a tabela usuários:
create table usuarios( id serial not null primary key, nome varchar(100), login varchar(50), senha varchar(50), status char(1) )
- Clique no botão para executar a instrução e criar a tabela no banco de dados Cadastro.
Concluindo esta etapa, você poderá ver a tabela usuários e as coluna criadas no Object Browser.
Se clicar com o botão direito sobre a tabela, verá um menu suspenso com diversas opções para gerenciá-la.
Clicando em View Data -> View Top 100 Rows, será aberta a janela onde você poderá incluir e visualizar os dados na tabela conforme figura abaixo:
Criando a solução no VS 2013 Express Edition for Windows Desktop
Abra o Visual Studio 2013 Express for Windows Desktop e clique em New Project. Selecione o template Visual Studio Solution e informe o nome ControleUsuarios e clique no botão OK.
Criamos uma solução vazia onde iremos, agora, incluir os nossos projetos.
No menu FILE clique em Add -> New Project;
A seguir, selecione o template Class Library e informe o nome Repositorio e clique no botão OK.
No menu FILE, clique em Add -> New Project.
Selecione o template Windows Forms Application e informe o nome Usuarios. Clique no botão Add;
Temos agora uma solução contendo dois projetos:
Incluindo as referências ao NHibernate, Fluent NHibernate e ao provedor Npgsql
Vamos agora criar 2 pastas no projeto Repositorio: clique com o botão direito do mouse sobre o projeto e a seguir clique em Add -> New Folder e informe o nome Entidades. Repita o procedimento acima e cria a pasta com o nome Mapeamento.
Vamos agora referenciar o NHibernate, o Fluent NHibernate e o provedor Npgsql para acessar o PostgreSQL usando o Nuget.
O papel do Nuget é justamente ser um gerenciador de bibliotecas de modo a garantir que todas as dll’s de um pacote estejam atualizadas com suas versões corretas, evitando assim erros de referência em seus projetos.
No menu TOOLS, clique em Library Package Manager -> Manage Nuget Packages for Solution;
Na janela Manage Nuget Packages, digite NHibernate para localizar o pacote e a seguir clique no botão Install;
Clique no botão OK para instalar o pacote nos projetos da solução.
Selecione a seguir o pacote FluentNHibernate e clique no botão Install, repetindo o procedimento feito:
Retorne a janela Manage Nuget Packages e digite Npgsql para localizar o pacote e a seguir clique no botão Install;
Ao final, teremos as referências ao NHibernate, Fluent NHibernate e ao provedor Npgsql instalados em nossa solução e estamos prontos para criar o Repositório, as entidades e o mapeamento ORM.
Criando as Entidades, o Mapeamento com Fluent NHibernate
Vamos começar definindo a entidade Usuario na pasta Entidades. Clique com o botão direito do mouse sobre a pasta Entidades e a seguir selecione Add -> Class.
Informe o nome Usuario.vb e digite o código abaixo neste arquivo:
Public Class Usuario Public Overridable Property Id As Integer Public Overridable Property Nome As String Public Overridable Property Login As String Public Overridable Property Senha As String Public Overridable Property Status As Char End Class
É importante usar o modificador Overridable na definição das propriedades e atentar que cada uma deve estar relacionada com as colunas da tabela usuarios criada no PostgreSQL.
Agora vamos criar o mapeamento ORM usando o Fluent NHibernate. Clique com o botão direito sobre a pasta Mapeamento e selecione Add -> Class.
Informe o nome UsuarioMap e digite o código abaixo neste arquivo:
Imports FluentNHibernate.Mapping Public Class UsuarioMap Inherits ClassMap(Of Usuario) Sub New() Id(Function(m) m.Id) Map(Function(m) m.Nome) Map(Function(m) m.Login) Map(Function(m) m.Senha) Map(Function(m) m.Status) Table("usuarios") End Sub End Class
Neste código, mapeamos as propriedades definidas na classe Usuário para os campos da tabela Usuários, definido na propriedade Table do Fluente NHibernate.
Usamos aqui as expressões lambdas que são funções que podem conter expressões e declarações que são usadas para criar delegates e árvores de expressões, onde o tipo das variáveis não precisam ser declarados, visto que elas usam métodos anônimos.
Para saber mais sobre expressões lambdas, veja .NET – Expressões Lambdas.
Criando a SessionFactory e o Repositório
Vamos começar criando uma classe chamada SessionFactory, que será responsável por disponibilizar uma session que representa o nosso contexto. Nesta classe iremos definir a string de conexão e a conexão com o banco de dados PostgreSQL.
No menu PROJECT clique em Add Class e informe o nome SessionFactory. Em seguida digite o código abaixo nesta classe:
Imports NHibernate Imports FluentNHibernate.Cfg.Db Imports FluentNHibernate.Cfg Public Class SessionFactory Private Shared ConnectionString As String = "Server=localhost; Port=5432; User Id=postgres; Password=********; Database=cadastro" Private Shared session As ISessionFactory Public Shared Function CriarSession() As ISessionFactory If session IsNot Nothing Then Return session End If Dim configDB As IPersistenceConfigurer = PostgreSQLConfiguration.PostgreSQL82.ConnectionString(ConnectionString) Dim configMap = Fluently.Configure().Database(configDB).Mappings(Function(c) c.FluentMappings.AddFromAssemblyOf(Of UsuarioMap)()) session = configMap.BuildSessionFactory() Return session End Function Public Shared Function AbrirSession() As ISession Return CriarSession().OpenSession() End Function End Class
A classe SessionFactory possui métodos estáticos para criar e abrir uma sessão que representa o contexto e a conexão com o banco de dados PostgreSQL. Logo após, vamos criar o nosso repositório.
Nesse projeto iremos usar o padrão Repository e criar um repositório genérico onde iremos definir os métodos de acesso aos dados.
O que é o padrão Repository?
Um repositório é essencialmente uma coleção de objetos de domínio em memória e, com base nisso, o padrão Repository permite realizar o isolamento entre a camada de acesso a dados (DAL) de sua aplicação e sua camada de apresentação (UI) e camada de negócios (BLL).
Ao utilizar o padrão Repository, você pode realizar a persistência e a separação de interesses em seu código de acesso a dados, visto que ele encapsula a lógica necessária para persistir os objetos do seu domínio na sua fonte de armazenamento de dados. Em suma, você pode usar o padrão Repository para desacoplar o modelo de domínio do código de acesso a dados.
Martin Fowler afirma: “O padrão Repository faz a mediação entre o domínio e as camadas de mapeamento de dados, agindo como uma coleção de objetos de domínio em memória… Conceitualmente, um repositório encapsula o conjunto de objetos persistidos em um armazenamento de dados e as operações realizadas sobre eles, fornecendo uma visão mais orientada a objetos da camada de persistência; e também dá suporte ao objetivo de alcançar uma separação limpa e uma forma de dependência entre o domínio e as camadas de mapeamento de dados”. (http://martinfowler.com/eaaCatalog/repository.html)
Em uma das implementações do padrão repositório podemos começar definindo uma interface que atuará como a nossa fachada de acesso aos dados. Vamos criar então uma interface chamada IUsuarioCrud.
Estando no projeto Repositorio, clique no menu PROJECT; depois clique em Add New Item e selecione o template Interface, informando o nome IUsuarioCrud e defina o código a seguir neste arquivo:
Public Interface IUsuarioCrud(Of T) Sub Inserir(entidade As T) Sub Alterar(entidade As T) Sub Excluir(entidade As T) Function BuscarPorId(Id As Integer) As T Function Consultar() As IList(Of T) End Interface
Temos assim uma interface definindo os métodos CRUD que deverá ser implementada por uma classe concreta que iremos criar e que se chamará Repositorio.vb.
Estando no projeto Repositorio clique no menu PROJECT clique em Add Class e selecione o template Class informando o nome Repositorio e a seguir defina o código abaixo:
Imports NHibernate Imports System.Linq Imports NHibernate.Linq Imports System.Linq.Expressions Public Class Repositorio(Of T As Class) Implements IUsuarioCrud(Of T) Public Sub Alterar(entidade As T) Implements IUsuarioCrud(Of T).Alterar Using session As ISession = SessionFactory.AbrirSession() Using transacao As ITransaction = session.BeginTransaction() Try session.Update(entidade) transacao.Commit() Catch ex As Exception If Not transacao.WasCommitted Then transacao.Rollback() End If Throw New Exception("Erro ao Alterar Cliente : " + ex.Message) End Try End Using End Using End Sub Public Sub Excluir(entidade As T) Implements IUsuarioCrud(Of T).Excluir Using session As ISession = SessionFactory.AbrirSession() Using transacao As ITransaction = session.BeginTransaction() Try session.Delete(entidade) transacao.Commit() Catch ex As Exception If Not transacao.WasCommitted Then transacao.Rollback() End If Throw New Exception("Erro ao Excluir Cliente : " + ex.Message) End Try End Using End Using End Sub Public Sub Inserir(entidade As T) Implements IUsuarioCrud(Of T).Inserir Using session As ISession = SessionFactory.AbrirSession() Using transacao As ITransaction = session.BeginTransaction() Try session.Save(entidade) transacao.Commit() Catch ex As Exception If Not transacao.WasCommitted Then transacao.Rollback() End If Throw New Exception("Erro ao inserir Cliente : " + ex.Message) End Try End Using End Using End Sub Public Function BuscarPorId(Id As Integer) As T Implements IUsuarioCrud(Of T).BuscarPorId Using session As ISession = SessionFactory.AbrirSession() Return session.Get(Of T)(Id) End Using End Function Public Function Consultar() As IList(Of T) Implements IUsuarioCrud(Of T).Consultar Using session As ISession = SessionFactory.AbrirSession() Return (From c In session.Query(Of T)() Select c).ToList() End Using End Function End Class
Vemos no código a implementação dos métodos CRUD da interface IUsuarioCrud. Agora só falta definir uma classe para que possamos usar o repositório genérico.
No menu PROJECT, clique em Add -> Class e informe o nome UsuarioRepositorio digitando o código abaixo neste classe:
Imports NHibernate Imports System.Linq Imports NHibernate.Linq Public Class UsuarioRepositorio Inherits Repositorio(Of Usuario) Public Function ValidarLogin(login As String) As Boolean Using session As ISession = SessionFactory.AbrirSession() Return (From e In session.Query(Of Usuario)() Where e.Login.Equals(login) Select e).Count > 0 End Using End Function Public Function ValidarAcesso(login As String, senha As String) As Boolean Using session As ISession = SessionFactory.AbrirSession() Return (From e In session.Query(Of Usuario)() Where e.Login.Equals(login) AndAlso e.Senha.Equals(senha) Select e).Count > 0 End Using End Function End Class
A nossa classe UsuarioRepositorio herda da classe Repositorio e inclui dois métodos usando consultas LINQ:
- ValidarLogin – que verifica se um login já esta cadastrado na tabela Usuários
- ValidarAcesso – que verifica o login e senha do usuário na tabela Usuários
Estamos prontos para usar o nosso repositório para acessar e persistir informações no PostgreSQL usando a classe UsuarioRepositorio.
Na continuação deste artigo irei mostrar a criação dos formulários de login e registro no projeto Windows Forms e mostrar como usar o nosso repositório para implementar o login e o registro de um novo usuário.