quinta-feira, abril 19, 2007

A mágica do DetachedCriteria

NHibernate é bom mesmo.

Eu tinha o seguinte código hoje pra otimizar (extraído de um Controller do projeto que estou trabalhando):

[Layout("popup")]
public void Observacoes([ARFetch] Pedido pedido, [ARFetch] Fornecedor fornecedor)
{
SimpleQuery consulta;

if (fornecedor == null) {
consulta = new SimpleQuery(@"
from ObservacaoPedido obs
where obs.Pedido = ?
order by obs.CriacaoData
", pedido);
}
else {
consulta = new SimpleQuery(@"
from ObservacaoPedido obs
where obs.Pedido = ? and obs.Fornecedor = ?
order by obs.CriacaoData
", pedido, fornecedor);
}

IEnumerable observacoes = consulta.Execute();

PropertyBag.Add("pedido", pedido);
PropertyBag.Add("fornecedor", fornecedor);
PropertyBag.Add("observacoes", observacoes);
}


Qual era o problema dele? A princípio, nenhum... Mas o NHibernate tem uma certa particularidade: quando o carregamento de objetos veio de uma consulta HQL, ele não cria proxies para os objetos (ou seja, sem lazy-loading para relacionamentos muitos-para-um), e só carrega exatamente o que diz minha consulta. O resultado é um turbilhão de consultas sendo enviadas ao banco, para carregar os dados que "faltaram"... Mesmo que eu não use eles.

Introduzindo, então, o DetachedCriteria:

public void Observacoes([ARFetch] Pedido pedido, [ARFetch] Fornecedor fornecedor) {
QueryBuilder q =
Where.ObservacaoPedido.Pedido == pedido;

DetachedCriteria crit = q;
crit.SetResultTransformer(new DistinctRootEntityResultTransformer());
crit.SetFetchMode("Anexos", FetchMode.Eager);
crit.SetFetchMode("Anexos.Arquivo", FetchMode.Eager);

IEnumerable observacoes =
ObservacaoPedido.List(crit, OrderBy.ObservacaoPedido.CriacaoData);

PropertyBag.Add("pedido", pedido);
PropertyBag.Add("fornecedor", fornecedor);
PropertyBag.Add("observacoes", observacoes);
}


O código, menor, ficou até um pouco mais claro, apesar de ter ficado mais arcano, expondo mais o NHibernate. Teria ficado mais ainda, se eu não tivesse utilizado o NHQG do Ayende para gerar o DetachedCriteria.

O resultado? Apenas uma consulta sendo enviada ao banco, e o tempo de carregamento de uma tela baixou de 3s pra 0,4s.

segunda-feira, abril 09, 2007

Google MyMaps

O Google acaba de lançar a interface MyMaps, onde qualquer um pode criar seu próprio mapa, sem precisar conhecer a API de mapas.

Parece interessante. Ainda não vi como usar, mas vi um mapa bem legal:

The World of Hello World: um mapa contendo as principais linguagens de programação, a indicação de onde foram inventadas, e um exemplo de código. É sempre legal rever aquele código COBOL ou Fortran e ficar aliviado, de como já passamos daquela fase.