3

This solution didn't work for me: C#/NHibernate - Get first 10 records ordered by grouped sum

My case is very similar, but I keep receveing the following error message:

Additional information: could not resolve property: Produto_Id of: SistemaVendas.Domain.venda.ProdutoVendido

My code so far:

ICriteria criteria = unitOfWork.Session
            .CreateCriteria<ProdutoVendido>("ProdutoVendido")
            .SetMaxResults(limite)
            .CreateCriteria("Produto_Id")
                .SetProjection(Projections.ProjectionList()
                    .Add(Projections.GroupProperty("Produto_Id"), "ID")
                    .Add(Projections.Sum("ProdutoVendido.Quantidade"), "QuantitySum")
                )
                .AddOrder(Order.Desc("QuantitySum"));

return criteria
            .SetResultTransformer(Transformers.AliasToBean<Produto>())
            .List<Produto>().ToList();

What am I doing wrong?

P.S. ProdutoVendido = SoldProduct and Produto = Product

ProdutoVendido mapping

    public ProdutoVendidoMap()
    {
        Id(x => x.Id).GeneratedBy.Identity();            

        Map(x => x.Quantidade);
        Map(x => x.Desconto);
        Map(x => x.Observacao).Length(ProdutoVendido.MAX_OBSERVACAO_LENGTH);            

        References(x => x.Venda)
            .Cascade.None();
        References(x => x.Produto)
            .Cascade.None();
    }

Edit:

Final solution

I just created this DTO, as @Radim Köhler pointed

public class ProdutoDto
{
    public ulong Id { get; set; }
    public int QuantidadeTotal { get; set; }
}

and my final NHibernate query is

ICriteria criteria = unitOfWork.Session
    .CreateCriteria<ProdutoVendido>("ProdutoVendido")
    .SetMaxResults(limite)            
    .CreateCriteria("Produto", "p")            
        .SetProjection(Projections.ProjectionList()
            .Add(Projections.GroupProperty("p.Id"), "Id")
            .Add(Projections.Sum("ProdutoVendido.Quantidade"), "QuantidadeTotal")                    
        )
        .AddOrder(Order.Desc("QuantidadeTotal"));

var ids = criteria
            .SetResultTransformer(Transformers.AliasToBean<ProdutoDto>())
            .List<ProdutoDto>();

return unitOfWork.Session
    .CreateCriteria<Produto>()                
    .Add(Restrictions.In("Id", ids.Select(x => x.Id).ToArray()))
    .List<Produto>().ToList();
Community
  • 1
  • 1
Latrova
  • 468
  • 6
  • 15

1 Answers1

0

To fix the error returned by NHibernate, we have to query existing Object model. In this case, the sold product (ProdutoVendido) references Produto, not Produto_Id

...
Session
  .CreateCriteria<ProdutoVendido>("ProdutoVendido")
  ...
  // this line is about joining reference
  // not the column
  //.CreateCriteria("Produto_Id")
  .CreateCriteria("Produto", "p") // "p" is now alias which we can use

Check similar working query e.g. here

EXTEND

What we would need to be able to project SUM property - is an DTO (not a POCO, just DTO for this purpose). Check this Q & A for inspiration Joining two tables with specific columns in nhibernate

This could be it:

public class ProdutoDto
{
    public virtual int ID { get; set; }
    public virtual decimal QuantitySum { get; set; } // the type should match
}

and we can use that as a projection target:

return criteria
        .SetResultTransformer(Transformers.AliasToBean<ProdutoDto>())
        .List<ProdutoDto>().ToList();
Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • I changed it, but now it returns me: Additional information: Could not find a setter for property 'QuantitySum' in class 'SistemaVendas.Domain.produto.Produto'. I need QuantitySum to order and select the top 10, how to fix this? – Latrova May 10 '16 at 17:11
  • 1
    What we would need is DTO. That will create a layer mapping the projection into entity... I extended the answer, hope it helps a bit – Radim Köhler May 10 '16 at 18:08