C# - Login com Fluent NHibernate, NHibernate 4.0 e PostGreSql - I


 Esta é a versão C# do mesmo artigo feito para o VB .NET que mostra como usar os Fluent NHibernate e 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 usando o padrão repository.

Na seção  NHibernate - Macoratti.net você vai encontrar muitos artigos que eu já escrevi mostrando como usar os recursos do NHibernate.

Se você já chegou a usar o NHibernate e não conhece o Fluent NHibernate deve saber que gerar os arquivos de mapeamento (.hbm) dá muito trabalho e que é uma tarefa  que esta sujeita a erros.

Pois se esse isso era um quesito que o desmotivava a usar o NHibernate fique sabendo que agora você não tem mais essa desculpa.

O Fluent NHibernate chegou (a 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)

<?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>

 

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);
  }
}

 

Arquivo XML .hbm código Fluent NHibernate equivalente

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

Aprendizado

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 usuarios que deverá possuir a seguinte estrutura:

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 usuarios
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.

Concluindo esta etapa você poderá ver a tabela usuarios 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 gerenciar a tabela.

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 a linguagem C# 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 e 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 e digite o código abaixo neste arquivo:

namespace Repositorio.Entidades
{
    public class Usuario
    {
        public virtual int Id { get; set; }
        public virtual string Nome { get; set; }
        public virtual string Login { get; set; }
        public virtual string Senha { get; set; }
        public virtual char Status { get; set; }
    }
}

E 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:

using Repositorio.Entidades;
using FluentNHibernate.Mapping;
namespace Repositorio.Mapeamento
{
    public class UsuarioMap :  ClassMap<Usuario>
    {
        public UsuarioMap() 
        {
            Id(c => c.Id);
            Map(c => c.Nome);
            Map(c => c.Login);
            Map(c => c.Senha);
            Map(c => c.Status);
            Table("usuarios");
        }
    }
}

Neste código mapeamos as propriedades definidas na classe Usuario para os campos da tabela usuarios definido na propriedade Table do Fluente NHibernate.

Usamos aqui as expressões lambdas que são funções 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 o meu artigo: .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:

using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
namespace Repositorio
{
    public class SessionFactory
    {
        private static string ConnectionString = "Server=localhost; Port=5432; User Id=postgres; Password=********; Database=cadastro";
        private static ISessionFactory session;
        public static ISessionFactory CriarSession()
        {
            if (session != null)
                return session;
            IPersistenceConfigurer configDB = PostgreSQLConfiguration.PostgreSQL82.ConnectionString(ConnectionString);
            var configMap = Fluently.Configure().Database(configDB).Mappings(c => c.FluentMappings.AddFromAssemblyOf<Mapeamento.Usuario.Map>());
            session = configMap.BuildSessionFactory();
            return session;
        }
        public static ISession AbrirSession()
        {
            return CriarSession().OpenSession();
        }
    }
}

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.

Após isso 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 da 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 clique em Add New Item e selecione o template Interface informando o nome IUsuarioCrud e defina o código a seguir neste arquivo:

using System.Collections.Generic;
namespace Repositorio
{
    public interface IUsuarioCrud<T>
    {
        void Inserir(T entidade);
        void Alterar(T entidade);
        void Excluir(T entidade);
        T RetornarPorId(int Id);
        IList<T> Consultar();
    }
}

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:

using NHibernate;
using System;
using System.Collections.Generic;
using NHibernate.Linq;
using System.Linq;
namespace Repositorio
{
    public class Repositorio<T> : IUsuarioCrud<T> where T : class
    {
        public void Inserir(T entidade)
        {
            using (ISession session = SessionFactory.AbrirSession())
            {
                using (ITransaction transacao = session.BeginTransaction())
                {
                    try
                    {
                        session.Save(entidade);
                        transacao.Commit();
                    }
                    catch (Exception ex)
                    {
                        if (!transacao.WasCommitted)
                        {
                            transacao.Rollback();
                        }
                        throw new Exception("Erro ao inserir Cliente : " + ex.Message);
                    }
                }
            }
        }
        public void Alterar(T entidade)
        {
            using (ISession session = SessionFactory.AbrirSession())
            {
                using (ITransaction transacao = session.BeginTransaction())
                {
                    try
                    {
                        session.Update(entidade);
                        transacao.Commit();
                    }
                    catch (Exception ex)
                    {
                        if (!transacao.WasCommitted)
                        {
                            transacao.Rollback();
                        }
                        throw new Exception("Erro ao Alterar Cliente : " + ex.Message);
                    }
                }
            }
        }
        public void Excluir(T entidade)
        {
            using (ISession session = SessionFactory.AbrirSession())
            {
                using (ITransaction transacao = session.BeginTransaction())
                {
                    try
                    {
                        session.Delete(entidade);
                        transacao.Commit();
                    }
                    catch (Exception ex)
                    {
                        if (!transacao.WasCommitted)
                        {
                            transacao.Rollback();
                        }
                        throw new Exception("Erro ao Excluir Cliente : " + ex.Message);
                    }
                }
            }
        }
        public T RetornarPorId(int Id)
        {
            using (ISession session = SessionFactory.AbrirSession())
            {
                return session.Get<T>(Id);
            }
        }
        public IList<T> Consultar()
        {
            using (ISession session = SessionFactory.AbrirSession())
            {
                return (from c in session.Query<T>() select c).ToList();
            }
        }
    }
}

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:

using System.Linq;
using Repositorio.Entidades;
using NHibernate;
using NHibernate.Linq;
namespace Repositorio.Mapeamento
{
    public class UsuarioRepositorio : Repositorio<Usuario>
    {
        public bool ValidarLogin(string login)
        {
	  using (ISession session = SessionFactory.AbrirSession()) 
               {
                    return (from e in session.Query<Usuario>() where e.Login.Equals(login) select e).Count() > 0;
	  }
        }
        public bool ValidarAcesso(string login, string senha)
        {
              using (ISession session = SessionFactory.AbrirSession()) 
              {
	       return (from e in session.Query<Usuario>() where e.Login.Equals(login) && e.Senha.Equals(senha) select e).Count() > 0;
	 }
        }
    }
}

A nossa classe UsuarioRepositorio herda da classe Repositorio e inclui dois métodos usando consultas LINQ:

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.

João 3:17 Porque Deus enviou o seu Filho ao mundo, não para que julgasse o mundo, mas para que o mundo fosse salvo por ele.

João 3:18 Quem crê nele não é julgado; mas quem não crê, já está julgado; porquanto não crê no nome do unigênito Filho de Deus.

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

 

             Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter
 

Referências:


José Carlos Macoratti