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 do meu site 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 está sujeita a erros. Se 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 (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 neste link.
Neste artigo eu vou criar um projeto Windows Forms usando a linguagem VB.NET e usando o NHibernate e Fluent NHibernate para 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 no (+) 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 defina 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:
- 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 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 e, 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 Usuários 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 Repositório.
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 crie 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 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 e o Mapeamento com Fluent NHibernate
Vamos começar definindo a entidade Usuário na pasta Entidades. Clique com o botão direito do mouse sobre a pasta Entidades e em seguida selecione Add -> Class.
Informe o nome Usuário 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 usuários, 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 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 e 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 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 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 Repositório, clique no menu PROJECT e clique em Add New Item. 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ão ser implementados por uma classe concreta, que iremos criar e que se chamará Repositorio.vb.
Estando no projeto Repositório, clique no menu PROJECT e depois em Add Class e selecione o template Class, informando o nome Repositório 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:
- 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.
















