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:
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:
- .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
- Disponibilidade do Nathan Brown para portar, Thanks Nathan!
O 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