C# - NHibernate e Fluent NHibernate : Criando tabelas no SQL Server 2012 (LocalDB)


 Este artigo mostra como usar o Fluent NHibernate e o NHibernate 4.0 para criar tabelas no SQL Server 2012 (LocalDB) criando classes POCO  e o mapeamento com Fluent NHibernate usando a linguagem Visual C#.

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 é uma tarefa  que esta sujeita a erros.

Pois, se esse 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.

Dessa forma o Fluent NHibernate oferece uma alternativa aos arquivos de mapeamento XML padrão do NHibernate. Ao invés de escrever documentos XML (arquivos .hbm.xml), o Fluent NHibernate permite que você escreva mapeamentos fortemente tipados usando código C# ou VB .NET.

Isso permite um fácil refatoramento, melhora a legibilidade e código fica mais conciso.

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 Console Application com a linguagem C#,  e, usando o NHibernate e Fluent NHibernate definir as classes POCO o mapeamento via código para criar as tabelas em tempo de execução no SQL Server 2012.

Recursos usados

Objetivos

Aprendizado

Criando um banco de dados no SQL Server 2012 Express

Para criar o banco de dados no SQL Server abra o Visual Studio 2013 Express Edition e no menu VIEW clique em OTHER Windows -> DataBase Explorer;

Na janela DataBase Explorer clique com o botão direito sobre Data Connections e a seguir em Add Connection...

A seguir informe o nome do servidor, eu estou usando o LocalDB definido conforme mostra a figura abaixo, e informe o nome do banco de dados que deseja criar. No exemplo estou criando o banco de dados TesteNHibernate.

Clique no botão OK e confirme a criação do banco de dados.

Pronto nosso banco de dados já esta criado e pronto para receber as tabelas que serão geradas em tempo de execução.

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 a linguagem C# o template Console Application e informe o nome NHibernate_Mapeamento_Fluent_NHibernate e clique no botão OK;

Vamos definir as classes do nosso modelo e realizar o mapeamento usando o Fluent NHibernate, mas antes temos que definir as referências ao NHibernate e ao Fluent NHibernate.

Incluindo as referências ao NHibernate e Fluent NHibernate

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:

Ao final teremos as referências ao NHibernate e ao Fluent NHibernate instalados em nossa solução e estamos prontos para criar as classes do nosso modelo e definir o mapeamento ORM.

Criando as Entidades e o Mapeamento com Fluent NHibernate

Vamos agora definir as classes que representam as entidades do nosso domínio. Como exemplo eu vou definir 3 classes :

Essas classes serão o nosso modelo de domínio.

Para simplificar eu vou criar todas as classes  no arquivo Programa.cs.

Eu poderia, e deveria, criar uma nova pasta chamada Entidades e definir nesta pasta as entidades e depois criar outra pasta chamada Mapeamento e criar nela as classes de mapeamento, mas vou criar todas as classes no arquivo Program.cs visto que este artigo tem o objetivo de mostrar a funcionalidade da criação das tabelas no SQL Server.

Define a seguir no arquivo Program.cs as classes conforme abaixo:

public class Fabricante
    {
        public virtual int Id { get; set; }
        public virtual string Nome { get; set; }
    }
    public class Modelo
    {
        public virtual int Id { get; set; }
        public virtual string Nome { get; set; }
        public virtual Fabricante Fabricante { get; set; }
    }
    public class Carro
    {
        public virtual int Id { get; set; }
        public virtual string Titulo { get; set; }
        public virtual Fabricante Fabricante { get; set; }
        public virtual Modelo Modelo { get; set; }
    }

E importante usar o modificador Virtual na definição das propriedades.

Note que temos uma referência a classe Fabricante na classe Modelo e na classe Carro temos as referências às classes Fabricante e Modelo indicando um relacionamento entre as classes.

Agora vamos criar o mapeamento ORM usando o Fluent NHibernate no arquivo Program.cs.

Digite o código abaixo mapeando cada classe e definindo as referências entre elas:

 public class FabricanteMap : ClassMap<Fabricante>
    {
        public FabricanteMap()
        {
            Id(x => x.Id);
            Map(x=> x.Nome);
        }
    }
    public class ModeloMap : ClassMap<Modelo>
    {
        public ModeloMap()
        {
            Id(x => x.Id);
            Map(x => x.Nome);
            References(x => x.Fabricante).Cascade.All();
        }
    }
    public class CarroMap : ClassMap<Carro>
    {
        public CarroMap()
        {
            Id(x => x.Id);
            Map(x => x.Titulo);
            References(x => x.Fabricante).Cascade.All();
            References(x => x.Modelo).Cascade.All();
        }
    }

Neste código mapeamos as propriedades definidas em cada classe e definimos as referências.

Cada mapeamento requer um Id de algum tipo, estes são mapeados usando o método Id; este método usa uma expressão lambda da propriedade que você deseja usar como seu ID.

As expressões lambdas 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

Dependendo do tipo de retorno da propriedade o Fluent NHibernate irá fazer algumas suposições sobre o tipo de identificador que você está usando. Por exemplo, se sua propriedade ID é um int, então vamos supor que você está usando uma coluna de identidade.

O mapeamento das propriedades é o mais comum e para isso podemos usar o método Map() que indica a propriedade mapeada.

Para expressar o relacionamento entre as classes usamos o método References pois no nosso exemplo temos somente uma única instância das entidades referenciadas se você estiver mapeando uma coleção vai precisar HasMany ou HasManyToMany.

No nosso exemplo estamos também usando a propriedade Cascade para definir a estratégia em Cascata de forma que ao criarmos os objetos relacionados não ocorra um erro em tempo de execução.

Criando a SessionFactory

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 SQL Server bem como inicializar a Session Factory definindo a classe SchemaExport de forma a criar os esquemas para as tabelas através da configuração e das classes POCO e respectivo mapeamento.

No menu PROJECT clique em Add Class e informe o nome NHibernteHelper. Em seguida digite o código abaixo nesta classe:

using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;

namespace NHibernate_Mapeamento_Fluent_NHibernate
{
    public class NHibernateHelper
    {
         private static ISessionFactory _sessionFactory;  

        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                    InitializeSessionFactory();

                return _sessionFactory;
            }

        }
        private static void InitializeSessionFactory()
        {
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2012.ConnectionString(@"Data Source=(LocalDB)\v11.0;Initial Catalog=TesteNHibernate;Integrated Security=True;").ShowSql()
                )
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Carro>()).ExposeConfiguration(cfg => new SchemaExport(cfg) .Create(true, true)).BuildSessionFactory();          
        }

      public static ISession OpenSession()
      {
            return SessionFactory.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 SQL Server.

No método InitializeSessionFactory() estamos definindo a string de conexão com o banco de dados TesteNHibernate que criamos no início do artigo. Note o método ShowSql() que irá exibir o SQL gerado na criação das tabelas.

O método Create da classe SchemaExport() é que irá permitir a criação dos esquemas definidos no código. Para isso precisamos do namespaces NHibernate.Tool.hbm2ddl.

Criando as tabelas

Agora falta definir o código no método Main() da classe Program onde iremos usar a SessionFactory e criar as instâncias das classes Fabricante, Modelo e Carro, salvar e dar o comit. Ao término desse processo veremos o SQL gerado no Console e as tabelas criadas  no banco de dados SQL Server.

Digite o código abaixo no método Main() da classe Program:

class Program
 {
        static void Main(string[] args)
        {
            using(var session = NHibernateHelper.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    var fordFabricante = new Fabricante
                                       {
                                           Nome = "Ford"
                                       };
                    var fiestaModelo = new Modelo
                                          {
                                              Nome = "Fiesta",
                                              Fabricante = fordFabricante
                                          };
                    var carro = new Carro
                                  {
                                      Fabricante = fordFabricante,
                                      Modelo     = fiestaModelo,
                                      Titulo     = "Carro do Macoratti"
                                  };
                    session.Save(carro);
                    transaction.Commit();
                    Console.WriteLine("Carro Criado com sucesso " + carro.Titulo);
                }
            }
           Console.ReadLine();
      }
 }

Executando o projeto iremos visualizar no console o seguinte resultado:

 

Examinando a janela DataBase Explorer veremos que no banco de dados TesteNHibernate foram criadas as tabelas : Carro, Fabricante e Modelo:

 

 

Clicando com o botão direito sobre a tabela Carro e selecionando Show Table Data veremos a informação incluída na tabela conforme figura abaixo:

 

 

Assim cumprimos nossa tarefa criando tabelas em um banco de dados SQL Server usando o NHibernate e o Fluent NHibernate via código.

 

Pegue o projeto completo aqui : NHibernate_Mapeamento_Fluent_NHibernate.zip

Mat 7:15 Guardai-vos dos falsos profetas, que vêm a vós disfarçados em ovelhas, mas interiormente são lobos devoradores.

Mat 7:16 Pelos seus frutos os conhecereis. Colhem-se, porventura, uvas dos espinheiros, ou figos dos abrolhos?

Mat 7:17 Assim, toda árvore boa produz bons frutos; porém a árvore má produz frutos maus.

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

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?


Referências:


José Carlos Macoratti