ASP .NET Core -  Usando o NHibernate e FluentNHibernate


A partir da versão 5.1 o NHibernate suporta o .NET Core 2.0 e o .NET Standard 2.0, e neste artigo eu mostro como usar o NHibernate e o FluenteNHibernate na ASP .NET Core.

Se você não conhece o NHibernate vou apresentá-lo...

O NHibernate é um porte do consagrado framework HIbernate do Java para a plataforma .NET, dessa forma o NHibernate surgiu a partir do Hibernate, um framework muito usado na plataforma Java.

O NHibernate é um framework para realizar o mapeamento objeto/relacional de modo a transformar os dados da estrutura lógica de um banco de dados relacional em objetos definidos no domínio de uma aplicação. Ele também realiza a persistência de objetos em banco de dados relacionais.

Ele é um concorrente do Entity Framework Core, sendo considerado uma ferramenta ORM padrão robusto e com um bom desempenho.

Outra boa notícia é que atualmente podemos também usar o FluentHibernate  para 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, e, ao invés de escrever documentos XML (arquivos .hbm.xml), ele permite que você escreva mapeamentos fortemente tipados usando código C# ou VB .NET.

Os bancos de dados suportados pelo NHibernate são :  SQL Server, SQL Server Azure, Oracle, PostgreSQL, MySQL, SQLite, DB2, Sybase daptive Server, Firebird, Informix.

Além disso ele também suporta o uso de OLE DB(Object Linking e Embedding) e do ODBC (Open Database Connectivity) e inclui os seguintes recursos:

Neste primeiro contato vou mostrar como usar o NHibernate em uma aplicação ASP .NET Core MVC acessando a tabela Livros do banco de dados LivrariaDemo do SQL Server e exibindo os livros em uma página.

Abaixo temos a estrutura da tabela Livros e a seguir os dados existentes na tabela: (Visualizados no Server Explorer)

Estamos usando assim uma abordagem database first.

Para poder usar o NHibernate e o FluentNHibernate temos que incluir os seguintes pacotes no projeto:

Podemos usar também o gerenciador de pacotes da solução via menu Tools -> Manage Nuget Packes for Solution

Vamos à prática...

Criando o projeto ASP .NET Core MVC

Abra o VS 2017 Community e crie um novo projeto .NET Core do tipo ASP .NET Core Web Application com o nome AspnCore_NHibernate1 (à seu gosto) :

A seguir selecione o template Web Application(Model-View-Controller) usando a ASP .NET Core 2.2.

Com o projeto criado inclua as referências aos pacotes do NHibernate e do FluentNHibernate:

1- NHibernate

2- FluentHibernate

Definindo o modelo de domínio e o mapeamento

Vamos agora definir o modelo de domínio na pasta Models criando a classe Livro:

    public class Livro
    {
        public virtual int LivroId { get; set; }
        public virtual string Titulo { get; set; }
    }

Definimos as propriedades LivroId e Titulo que irão mapear para os campos das tabela Livros.

Note que usamos o modificador virtual que é usado para modificar uma declaração de método, propriedade, indexador ou evento e permitir que ela seja substituída em uma classe derivada.(usando o modificador override).

Vamos agora criar uma pasta chamada Mappings no projeto e criar a classe LivroMap nesta pasta onde vamos definir o mapeamento ORM. A seguir temos o código da classe LivroMap:

using AspnCore_NHibernate1.Models;
using FluentNHibernate.Mapping;
namespace AspnCore_NHibernate1.Mapping
{
    public class LivroMap : ClassMap<Livro>
    {
        public LivroMap()
        {
            Id(l => l.LivroId);
            Map(l => l.Titulo);
            Table("Livros");
        }
    }
}

Nesta classe fazemos o mapamento das propriedades da nossa entidade Livro para a tabela.

Estamos usando os seguintes tipos de mapeamento:

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

Além desses recursos podemos fazer o mapeamento dos relacionamentos também.

Configurando a sessão com o banco de dados

Vamos configurar a sessão com o banco de dados onde vamos criar uma instância e definir o provedor usado e a string de conexão com o banco de dados.

Abra o arquivo Startup.cs e no método ConfigureServices inclua o código destacado em azul abaixo:

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            var connStr = Configuration.GetConnectionString("DefaultConnection");
            var _sessionFactory = Fluently.Configure()
                                      .Database(MsSqlConfiguration.MsSql2012.ConnectionString(connStr))
                                      .Mappings(m => m.FluentMappings.AddFromAssembly(GetType().Assembly))
                                      .BuildSessionFactory();
            services.AddScoped(factory =>
            {
                return _sessionFactory.OpenSession();
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

Neste código obtemos a string de conexão a seguir definimos uma instância da sessionfactory informando a string de conexão usada e o provedor do banco de dados SqlServer.

A seguir estamos retornando uma instância da conexão com o banco de dados aberta usando AddScoped o que garante que teremos aberta apenas uma conexão.

Criando o controlador e a view

Já podemos criar o controlador e definir o método Action para obter os dados.

Na pasta Controllers crie um controlador vazio chamado LivrosController e inclua o código abaixo:

using Microsoft.AspNetCore.Mvc;
using NHibernate;
using System.Linq;
namespace AspnCore_NHibernate1.Controllers
{
    public class LivrosController : Controller
    {
        private readonly ISession _session;
        public LivrosController(ISession session)
        {
            _session = session;
        }
        public IActionResult Index()
        {
            var list = _session.Query<Models.Livro>().ToList();
            return View(list);
        }
    }
}

Estamos injetando via DI uma instância de ISession no construtor do controlador o que nos dá acesso ao contexto que representa uma sessão com o banco de dados.

No método Action Index usamos essa instãncia para obter os dados da tabela Livros.

Eu poderia usar métodos assíncronos e também o LINQ para realizar consultas.

Agora basta criar a View Index.cshtml na pasta Views/Livros com o código a seguir:

Nota: Para criar a View clique com o botão direito do mouse sobre o método Action Index e selecione Add View.

@model IEnumerable<AspnCore_NHibernate1.Models.Livro>
@{
    ViewData["Title"] = "Index";
}
<h1>Relação de Livros</h1>
<p>
    <a asp-action="Create">Criar Novo</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.LivroId)</th>
            <th>@Html.DisplayNameFor(model => model.Titulo)</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>@Html.DisplayFor(modelItem => item.LivroId)</td>
            <td>@Html.DisplayFor(modelItem => item.Titulo)</td>
            <td>
                @Html.ActionLink("Edit", "Editar", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Details", "Detalhes", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Deletar", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
}
    </tbody>
</table>

Agora é só alegria...

Executando o projeto iremos obter o seguinte resultado:

Nota: Eu fiz uns ajustes no arquivo _Layout.cshtml da pasta Shared incluindo um link para o controlador Livros.

Fizemos assim nosso primeiro contato com o NHibernate na .NET Core. Aguarde mais novidades em breve.

Pegue o código do projeto aqui: AspnCore_NHibernate1.zip

"E, quanto fizerdes por palavras ou por obras, fazei tudo em nome do Senhor Jesus, dando por ele graças a Deus Pai."
Colossenses 3:17

Referências:


José Carlos Macoratti