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 tinhamos 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, é ncessá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; } }
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($"Cidades com mais de 1000 pessoas:"); cities.ForEach(x => { Console.WriteLine($"{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 cidade que tem 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 código desse post pode ser visto aqui.
Recomendo dar uma lida na thread desse Pull Request no GitHub
Vamos torcer para sair logo! E aí o que acharam da novidade?
Victor Cavalcante
Victor Cavalcante é marido da Mariana Frioli, pai do Eduardo, Microsoft MVP, trabalha com desenvolvimento web a 11 anos e é focado em padrões de desenvolvimento para web. Trabalha na Lambda3 (www.lambda3.com.br), empresa ágil que insiste em fazer software certo. É ainda professor universitário e atua no grupo .NET Architects desde seu início. Acompanhe seu twitter para saber as novidades:@vcavalcante.