.NET

7 out, 2014

Login com Fluent NHibernate, NHibernate 4.0 e PostgreSQL – Parte 01

Publicidade

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

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:

c_pgsql1

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:

c_pgsql4

Na janela New DataBase informe o nome do banco de dados – Cadastro e define o Owner como sendo o usuário postgres:

c_pgsql5

Agora vamos criar a nossa tabela usuários. Para isso, faça o seguinte:

  1. Selecione o objeto Tables()
  2. Clique no menu SQL
  3. 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)
                )
  1. Clique no botão para executar a instrução e criar a tabela no banco de dados Cadastro.

c_lpgnh8

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:

c_lpgnh9

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.

c_lpgnh1

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.

c_lpgnh2

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:

c_lpgnh3

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;

c_lpgnh4

Na janela Manage Nuget Packages, digite NHibernate para localizar o pacote e a seguir clique no botão Install;

c_lpgnh5

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:

c_lpgnh6

Retorne a janela Manage Nuget Packages e digite Npgsql para localizar o pacote e a seguir clique no botão Install;

c_lpgnh7

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.