.NET

27 set, 2017

NHibernate no .NET Core 2 está quase pronto!

Publicidade

Quem me conhece sabe como sou fã no NHibernate. Já utilizo há vários anos e já se comprovou como um ORM completo e confiável. Se você não conhece, dê uma lida nestes sites para conhecer:

  1. http://nhibernate.info
  2. https://github.com/nhibernate

Mas mesmo gostando do NHibernate, ele tinha se tornado um problema desde o lançamento do .NET Core. Na verdade, ele não era o problema; mas sim a falta dele no ecossistema do .NET Core. A Microsoft lançou em conjunto com o .NET Core o Entity Framework Core, mas como pode ser visto no roadmap do EF, ele ainda tem algumas features faltando para ser considerado um ORM completo.

A esperança era que, em algum momento, o NHibernate fosse portado para o .NET Core. A esperança era pequena porque a dependência por APIs do .NET Framework (full framework) era grande. Nesse vácuo, outros frameworks começaram a se despontar como o Dapper, mas não dá para comparar as features que tínhamos no NHibernate com um micro ORM.

Quando a Microsoft anunciou o .NET Standard 2.0, as esperanças renasceram. A proposta de incorporar uma boa parte das APIs do .NET Framework no .NET Core era muito animadora – até gravamos um podcast sobre isso.

A partir desse anuncio, fiquei monitorando o repositório do NHibernate Core para ver como estava o andamento do trabalho, até surgir a branch NH999 que está ligado ao porte do NH para o .NET Core 2. Fiquei animado e monitorando os PRs do NH até ver que, em agosto, o Nathan Brown fez um PR no qual ele fala que os testes já estão passando no Windows com SQL Server e ele já estava disponibilizando os nugets em um feed público.

Na mesma semana, fui testar e estava funcionando. Vou mostrar para vocês como vocês podem reproduzir esse teste, porque se vocês forem como eu, só vão acreditar vendo.

Mão na massa

Primeira coisa, é necessário configurar no Visual Studio um novo Feed de Nuget. Adicione a URL https://ci.appveyor.com/nuget/nhibernate-core-6cm11v2xdhud como um source de Nuget.

Adicione o pacote NHibernate.Driver.SqlServer. Não se esqueça de pesquisar no feed que você acabou de adicionar. É necessário marcar a opção pré-release:

Depois de instalado, vamos criar a configuração do NHibernate a moda antiga, com os benditos XML (eu costumo fazer mapeamento com o Fluent NHibernate, mas ele ainda não está portado). Para o nosso teste, essa configuração será suficiente. Primeiro, vamos configurar a conexão com um arquivo hibernate.cfg.xml. Esse arquivo deve estar na raiz do projeto e deve ser configurado nas propriedades do arquivo do projeto que o Build Action para None e Copy do output Directory para Copy Aways, o conteúdo do arquivo será o seguinte:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
      <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
  </configSections>
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.connection_string">Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=NHTeste;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False</property>
      <property name="dialect">NHibernate.Dialect.MsSql2012Dialect</property>
      <mapping assembly="ConsoleApp1"/>
    </session-factory>
  </hibernate-configuration>
</configuration>

Vamos mapear uma entidade simples para inserir e logo depois ler os dados. A entidade e a tabela estão logo abaixo:

    public class City
    {
        public virtual int Id { get;  set; }
        public virtual long Population { get; set; }
        public virtual string Name { get; set; }
    }
[\code]
 
 
CREATE TABLE [dbo].[City] (
    [Id]         INT           IDENTITY (1, 1) NOT NULL,
    [Name]       VARCHAR (255) NULL,
    [Population] BIGINT        NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC)

O arquivo de mapeamento tem o nome de Mapping.hbm.xml esse arquivo deve estar na raiz do projeto e deve ser configurado nas propriedades do arquivo do projeto que o Build Action para Embeded Resource e Copy do output Directory para Do not copy, o conteúdo do arquivo será o seguinte:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="ConsoleApp1" namespace="ConsoleApp1" auto-import="true">
  <class name="City">
    <id name="Id" type="int" generator="identity"/>
    <property name="Name" />
    <property name="Population" />
  </class>
</hibernate-mapping>

Chegando nesse ponto, basta fazer a conexão para obter a sessão do NHibernate, fiz tudo em um console application bem simples só para demonstrar que ele insere e consegue selecionar valores.

class Program
{
    static void Main(string[] args)
    {
         
         
        var configuration = new Configuration();
        configuration.Configure();
        var SessionFactory = configuration.BuildSessionFactory();
        var session = SessionFactory.OpenSession();
 
        Console.Write("Digite o nome da Cidade =");
        var name = Console.ReadLine();
 
        Console.Write("Digite a populaçao=");
        var population = Console.ReadLine();
 
 
        var city = new City { Name = name, Population = Convert.ToInt16(population) };
        session.SaveOrUpdate(city);
        session.Flush();
 
        var cities = session.Query<City>()
            .Where(p => p.Population > 1000)
            .ToList();
 
        Console.WriteLine(quot;Cidades com mais de 1000 pessoas:");
        cities.ForEach(x =>
        {
            Console.WriteLine(quot;{x.Name} -> {x.Population}");
        });
        Console.ReadLine();
        session.Close();
 
    }
}

Quando você executar o programa, ele irá pedir um nome da cidade depois da população inserir e exibir as cidades que têm mais de 1000.

Como eu disse, o teste é bem simples, mas já dá para ver que o trabalho está seguindo e que logo teremos tudo funcionando.

Isso tudo só foi possível por causa de 2 fatores:

  1. .NET Standard 2 está cobrindo muito mais APIs que o .NET Framewok já cobria. Com isso, ficou muito mais fácil para a equipe do NHibernate portar para o .NET Core 2.0
  2. Disponibilidade do Nathan Brown para portar, Thanks Nathan!

aqui está o código desse artigo.

Recomendo dar uma lida na thread desse Pull Request no GitHub.

Vamos torcer para sair logo! E aí o que acharam da novidade?

***

Este artigo foi produzido em parceria com a Lambda3. Leia outros conteúdos no blog da empresa: blog.lambda3.com.br