Esse post é um update do post do Victor Cavalcante do final do ano passado, onde ele analisava um pull request pendente do NHibernate que traria suporte ao .NET Standard para o NH.

Aquele PR ainda está ativo e não foi integrado até hoje. Por outro lado, outro PR acabou entrando, o #1523. Ele é menos ambicioso que o anterior, mas acabou por resolver. O release ainda está pendente por algumas dependências, mas pode acontecer a qualquer momento.

Eu testei rapidamente a implementação e funcionou perfeitamente. Diferentemente do caso do PR testado pelo Victor, neste caso não havia um pacote no Nuget, tive que baixar diretamente a dll do NHibernate.

Outra diferença é que o trabalho de separar os drivers, que estava integrado no PR anterior, ainda não entrou, então não vai aparecer neste exemplo (veja no exemplo do Victor o uso do NHibernate.Driver.SqlServer).

Testando a versão atualizada na branch principal

Para testar, vá até os commits do NHibernate na branch master e clique no check verde, e escolha os detalhes do segundo item, chamado de “NHibernate (Release Package) (NHibernate)”. Você vai cair em uma tela do Team City, e pode logar usando o login anônimo. Clique na aba “Artifacts” e baixe a dll de NHibernate-5.0.3/nuget_gallery/NHibernate-5.0.3.nupkg/lib/netstandard2.0/NHibernate.dll. Lá também tem o xml dos docs.

Se quiser baixar a última compilada quando este post foi escrito e que eu testei, ela é de 5 de Março, e está aqui:

Para testar, crie um projeto .NET Core 2.0 e adicione as seguintes referências:

  • Antlr3.Runtime
  • Iesi.Collections
  • Remotion.Linq
  • Remotion.Linq.EagerFetching
  • System.Configuration.ConfigurationManager
  • System.Data.SqlClient
  • System.Security.Permissions

Todos esses pacotes suportam .NET Standard.

As recomendações do post anterior do Victor sobre os arquivos hbm e xml também valem.

O arquivo final de projeto (csproj) ficará assim:

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
 <OutputType>Exe</OutputType>
 <TargetFramework>netcoreapp2.0</TargetFramework>
 </PropertyGroup>
 <ItemGroup>
 <EmbeddedResource Include="Mapping.hbm.xml" />
 <None Update="hibernate.cfg.xml">
 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 </None>
 </ItemGroup>
 <ItemGroup>
 <PackageReference Include="Antlr3.Runtime" Version="3.5.1" />
 <PackageReference Include="Iesi.Collections" Version="4.0.4" />
 <PackageReference Include="Remotion.Linq" Version="2.2.0" />
 <PackageReference Include="Remotion.Linq.EagerFetching" Version="2.1.0" />
 <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.1" />
 <PackageReference Include="System.Data.SqlClient" Version="4.4.2" />
 <PackageReference Include="System.Security.Permissions" Version="4.4.1" />
 </ItemGroup>
 <ItemGroup>
 <Reference Include="NHibernate">
 <HintPath>/caminho/para/o/NHibernate.dll</HintPath>
 </Reference>
 </ItemGroup>
</Project>

Com isso já é possível rodar o projeto. Dê uma olhada nos arquivos que o Victor recomenda, eles rodaram sem alterações.

Testei o projeto no Windows com Localdb, e também no Linux, com Sql Server também no Linux, e funcionou perfeitamente. Pra fazer isso altere a string de conexão no arquivo hibernate.cfg.xml. O resto fica exatamente igual.

O projeto está no meu Github, em giggio/exemplonhdnetstandard2.

Conclusão

Acredito que em algumas semanas (meses no pior cenário) o NH estará pronto para rodar no .NET Standard (e portanto no .NET Core). O interessante é que temos utilizado o Entity Framework este tempo todo com o .NET Core, por ser o único ORM decente até o momento (outros como Dapper tem propostas diferentes). Ao longo deste período, o EF teve todo o espaço para ganhar este mercado, já que estava isolado do seu principal concorrente, o NH. Essa vantagem está prestes a terminar, e o EF até hoje não tem suporte a funcionalidades fundamentais que se esperam de um ORM, como lazy loading (prevista de forma bastante básica para a versão 2.1, que deve ser lançada este ano). Apesar do endosso da Microsoft, acredito que o NH acabará ganhando a liderança no .NET Core, assim como aconteceu por tantos anos no .NET Framework.

Por outro lado, o .NET Core se fortalece bastante com um ORM mais completo. Sem dúvida essa ausência é problemática para o .NET Core, e está prestes a ser resolvida.