Eu já comentei aqui sobre o Grupo .Net Architects em que participo e recomendo.

O grupo, geralmente a cada 3 semanas, se reúne para debater e apresentar temas voltados a tecnologia e arquitetura de sistemas, na última apresentação, o André Dias apresentou para o grupo o Team System da Microsoft. Outras apresentações foram sobre Scrum, com Antonio Zegunis e DDD com o Giovanni Bassi apresentando.

E em um dos debates do grupo, foi proposto que eu apresentasse ao grupo o Ruby on Rails, já que eu sempre fazia uma analogia .NET x RoR. Mas ao invés de apresentar, convidei uma autoridade no assunto que prontamente aceitou o convite, o Fabio Akita do blog Akita On Rails.

O Fabio Akita é uma das personalidades mais importantes sobre Rails no Brasil, junto do Carlos Brando e outros feras em Rails.

Portanto, se você já ouviu falar e tem curiosidade sobre Ruby on Rails ou se já conhece e quer saber mais a respeito, será uma ótima oportunidade. A apresentação será dia 7 de Março de 2009 e é “free”, só é necessário você enviar um email para o Giovanni Bassi com alguns dados para autorizarem sua entrada na UNIP Jaguaré, onde é realizada as reuniões do grupo. Clique aqui para saber como.

Confirmando a data, dia 7 de Março de 2009.

Local da Apresentação:

UNIP Jaguaré (Cidade Universitária/Marginal Pinheiros)
Av. Torres de Oliveira, 330 – Jaguaré, São Paulo – SP
CEP 05347-020
Tel.: (11) 3767-5800
Ampliar o mapa do local.

Há estacionamento próximo ao local, e também é possível parar em uma rua sem saída próxima.

Nos encontramos na UNIP Jaguaré então, dia 7 ein !!!

[]´s

Lancei ontem um projeto de tradução da documentação oficial do NHibernate 2.0 par ao português do Brasil. Nesse lançamento o prefácio e o capítulo 1 já foram traduzidos por mim.

Na verdade não sei como ninguém ainda teve essa iniciativa já que o NHibernate é uma das melhores ferramentas de ORM para a plataforma .Net e tem sido muito usada aqui no Brasil.

Vejam e colaborem em Tradução da Documentação Oficial do NHibernate 2.0

Espero que a comunidade aceite bem essa iniciativa de tradução da documentação assim como conto com a ajuda de todos para chegar ao fim da tradução, afinal, a documentação é bem extensa. Dei uma estilizada no logo para ficar mais com uma cara de Brasil. Gostaram?

[]´s

, ,

Um dos recursos que encontramos no NHibernate para executar queries nos nossos objetos é a HQL, que é simples e sua curva de aprendizado é bem rápida, já que ela tem uma sintaxe muito semelhante ao nosso SQL Ansi. Você poderá usar HQL em 80% de suas queries, mas em casos específicos necessitamos de outro recurso também muito eficiente e bem legal. São as Criteria Queries.

Com Criteria Queries podemos fazer queries programaticamente, com uma interface fluente nos nossos objetos do Nhibernate.

Com HQL e com Criteria Queries podemos fazer a mesma coisa, porém ao lermos nosso código teremos percepções diferentes. Para demonstrarmos o uso de NHibernate ResultTransform vou fazer as nossas queries das duas maneiras, com HQL e com Criteria Queries, assim vocês podem ter uma melhor visualização do que é mais legal para vocês trabalharem.

E em alguns casos, o resultado de nossas queries pode ser passado com através de um DTO, ou seja, uma classes de Data Transfer Object.

E em que caso podemos usar uma classe DTO?

Imagine que temos uma entidade de histórico de visitação de seu site.

Em qualquer relatório da nossa classe histórico para demonstrarmos a quantidade de acessos, certamente precisaremos agrupar os dados do histórico, por exemplo, agrupado por data, horários, ip, etc. Em qualquer um desses casos, um valor que será importante nesse agrupamento é a quantidade de registros que contem em cada grupo, de que adianta agruparmos os históricos do dia X sem sabermos a quantidade de acessos não é mesmo.

Então podemos “transformar” nosso resultado em uma classe fora do domínio de nossa aplicação, ou seja, uma classe DTO apenas para passarmos os dados do relatório. Vejam um exemplo abaixo de uma classe DTO:

Com isso, iriamos facilitar o acesso aos dados das nossas queries.

E como transformarmos nossos resultados? Com NHibernate ResultTransform. Esse recurso é pouco documentado e só achamos bons exemplos em blogs.

Vamos a um exemplo. Vamos agrupar por dias:

Em HQL:

IList histoticos = session.CreateQuery("select h.Ip, count(*) from Historico h group by h.Ip").List();

Com Criteria Queries

IList historicos = session.CreateCriteria(typeof(Historico))
.SetProjection(Projections.ProjectionList()
.Add(Projections.RowCount())
.Add(Projections.GroupProperty("Ip"))
).List();

Vejam nosso objeto “históricos” na nossa janela de “Locals” do Visual Studio, o resultado da nossa query.

As propriedades do nosso objeto são índices de arrays e para trabalhar dessa forma, podemos encontrar algumas dificuldades. Para transformarmos esse resultado em um objeto da classe HistoricoDTO usamos o ResultTransfom. Vamos a ele então.

Para transformarmos o nosso objeto acima em HistoricoDTO, iremos dar um “apelido” (alias) a nossas projeções, para que assim, o NHibernate “transforme” o resultado da query em HistoricoDTO.

Vamos ao HQL com nossos “apelido” (alias) as propriedades que iremos gerar:

IList criterio = session.CreateQuery("select h.Ip as IP, count(*) as Qnt from Historico h group by h.Ip")
.SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean(typeof(HistoricoDTO))).List();

Aqui encontramos nossa primeira limitação no HQL. O HQL não suporta “apelidos” (alias) em suas projeções, por isso agora, recorremos ao Criteria Queries que suporta alias. Vejam como fica nosso código:

IList historicos = session.CreateCriteria(typeof(Historico))
.SetProjection(Projections.ProjectionList()
.Add(Projections.RowCount(), "QuantidadeDeAcessos")
.Add(Projections.GroupProperty("Ip"), "DescricaoDoGrupo")
).SetResultTransformer(Transformers.AliasToBean(typeof(HistoricoDTO))).List();

A segunda sobrecarga do método Add recebe uma string de Alias, que deve ser igual ao nome da propriedade de nossa DTO que desejamos “mapear”. Veja que antes de CreateCriteria retornar uma List() ele executa o método SetResultTransformer, que é onde indicamos a forma de “transformação” do resultado no objeto DTO. No nosso caso, indicamos o método estático da classe Transformer (namespace NHibernate.Transform) chamado AliasToBean, ou seja, “Apelido para Bean” (herança do irmão mais velho, o Hibernate escrito em Java). Esse Transformers.AliasToBean(typeof(HistoricoDTO)) portanto indica ao “transformador” do NHibernate usar o apelido da projeção como o nome da propriedade do objeto que passamos em typeof(HistoricoDTO).

Vejam como nosso objeto ficou na janela Locals:

Bem melhor agora, não é? Bem, vamos melhorar mais um pouco. Da forma que está, sempre necessitaríamos fazer um cast para trabalharmos com cada item da lista historicos, então para isso vamos deixar nossos amigos do Java com um pouco de inveja, usando o poder do Generics. Em NHibernate podemos retornar List() e também List<T>(). E isso é muito simples, vejam:

IList<HistoricoDTO> historicos = session.CreateCriteria(typeof(Historico))
.SetProjection(Projections.ProjectionList()
.Add(Projections.RowCount(), "QuantidadeDeAcessos")
.Add(Projections.GroupProperty("Ip"), "DescricaoDoGrupo")
).SetResultTransformer(Transformers.AliasToBean(typeof(HistoricoDTO))).List<HistoricoDTO>();

Pronto, agora não precisamos mais de casts em cada item de historicos.

Estou disponibilizando o código fonte com algumas coisas para facilitar a vida nos testes de quem quiser ver funcionando.

Junto do projeto existe um arquivo Default.aspx que vocês devem executar para criar a tabela e 1000 registros de testes que são criados usando números randomicos para a criação dos registros. O banco de dados que eu uso é o NHTestes, portanto, é só criarem o banco. O nome da instancia do SQL Server que eu uso é a “SQLExpress” em localhost, portanto o NHibernate vai tentar conectar em “localhost\sqlexpress”.

Ao executarem o “Default.aspx” e após gravar os 1000 registros de testes vai ser redirecionado para “NHibernateResultTransformer.aspx” onde vocês encontraram um menu para a chamada dos métodos e com os breakpoints já apontados.

Divirtão-se!

Fonte do Projeto de Exemplo

EDIT:

Para agrupamentos utilizando HQL, o Giovanni Bassi, membro fundador do Grupo .NET Architects, deu a opção de criarmos um construtor na classe HistoricoDTO que receba os valores DescricaoDoGrupo e QuantidadeDeAcessos. Nesse caso a HQL ficaria da seguinte maneira:

    IList<HistoricoDTO> historicos = _session.CreateQuery("select new HistoricoDTO(h.Ip, count(h.Ip)) from Historico h group by h.Ip").List<HistoricoDTO>();

Notem que na HQL, instanciamos o objeto com a instrução new HistoricoDTO(h.Ip, count(h.Ip)) e no contrutor de HistoricoDTO é passado os valores no nosso agrupamento. Realmente é uma opção bem interessante dessa forma também. Porém necessitamos mapear nossa classe da seguinte forma:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateResultTransformer.DomainModel" >
  <import class="NHibernateResultTransformer.DomainModel.HistoricoDTO, NHibernateResultTransformer.DomainModel"/>
</hibernate-mapping>

[]´s