Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate: Get distinct results based on a column, but retrieve all columns

I have a table GL that contains GLCode. I need to get a list of unique GLCodes, but get all the other columns. The following SQL produces the results I want.

select * from GL where GLId in (select Min(GLId) from GL group by GLCode )

Is there a way to do this using the Criteria API?

This is my best attempt:

        var subQuery = DetachedCriteria.For<GL>();
        subQuery
            .SetProjection(Projections.Property("GLCode"))                
            .SetResultTransformer(new DistinctRootEntityResultTransformer());

        return (List<GL>)currentSession
            .CreateCriteria(typeof(GL))
            .Add(Subqueries.PropertyIn("GLCode", subQuery))
            .List<GL>();   
like image 976
Alistair Avatar asked Jan 13 '10 04:01

Alistair


People also ask

How to remove duplicate entries from a list in NHibernate?

That's actually pretty easy with NHibernate, thanks to the result transformers. all you need to do is add .SetResultTransformer (new DistinctRootEntityResultTransformer ()) to either your query, or criteria, and NHibernate will remove duplicate entries from the resulted list.

How are IQueryable queries obtained in NHibernate?

IQueryable queries are obtained with the Query methods used on the ISession or IStatelessSession. (Prior to NHibernate 5.0, these methods were extensions defined in the NHibernate.Linq namespace.) A number of NHibernate Linq extensions giving access to NHibernate specific features are defined in the NHibernate.Linq namespace.

How to create queries from entity collection in NHibernate?

Starting with NHibernate 5.0, queries can also be created from an entity collection, with the standard Linq extension AsQueryable available from System.Linq namespace. IList<Cat> whiteKittens = cat.Kittens.AsQueryable () .Where (k => k.Color == "white") .ToList ();

How do I evaluate a method call in NHibernate?

Since NHibernate v5.0, the Linq provider will no more evaluate in-memory the method call even when it does not depend on the queried data. If you wish to have the method call evaluated before querying whenever possible, and then replaced in the query by its resulting value, specify LinqExtensionPreEvaluation.AllowPreEvaluation on the attribute.


1 Answers

Even though NHibernate doesn't have a way to exclude GLCode from the subquery's result columns, it is still possible to create a query that does the job. Use a correlated EXISTS subquery instead of IN. The SQL we're shooting for is like this:

select query.*
from GL query
where exists (
    select
        min(subquery.GLId) AS GLId,
        subquery.GLCode
    from GL subquery
    group by subquery.GLCode
    having min(subquery.GLId) = query.GLId);

And here's the NHibernate query:

var min = Projections.Min("GLId");

var subquery = DetachedCriteria.For<GL>("subquery")
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.GroupProperty("GLCode"), "GLCode")
        .Add(min, "GLId"))
    .Add(Restrictions.EqProperty(min, "query.GLId"));

return session.CreateCriteria<GL>("query")
    .Add(Subqueries.Exists(subquery))
    .List<GL>();
like image 179
Daniel Schilling Avatar answered Nov 15 '22 10:11

Daniel Schilling