Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Distinct result set from NHibernate using Criteria API?

Tags:

nhibernate

I'm trying to get distinct results using the Criteria API in NHibernate. I know this is possible using HQL, but I would prefer to do this using the Criteria API, because the rest of my app is written using only this method. I found this forum post, but haven't been able to get it to work. Is there a way with the criteria API to get distinct result sets?

Edit: In doing this, I also wanted to exclude the Primary Key column, which is also an identity, and get the remaining distinct records. Is there a way to do this? As it is, the distinct records are returning duplicates because the primary key is unique for each row, but all other fields are the same.

like image 242
Mark Struzinski Avatar asked Nov 25 '08 17:11

Mark Struzinski


2 Answers

To perform a distinct query you can set the projection on the criteria to Projections.Distinct. You then include the columns that you wish to return. The result is then turned back into an strongly-typed object by setting the result transformer to AliasToBeanResultTransformer - passing in the type that the result should be transformed into. In this example I am using the same type as the entity itself but you could create another class specifically for this query.

ICriteria criteria = session.CreateCriteria(typeof(Person)); criteria.SetProjection(     Projections.Distinct(Projections.ProjectionList()         .Add(Projections.Alias(Projections.Property("FirstName"), "FirstName"))         .Add(Projections.Alias(Projections.Property("LastName"), "LastName"))));  criteria.SetResultTransformer(     new NHibernate.Transform.AliasToBeanResultTransformer(typeof(Person)));  IList<Person> people = criteria.List<Person>(); 

This creates SQL similar to (in SQL Server at least):

SELECT DISTINCT FirstName, LastName from Person 

Please be aware that only the properties that you specify in your projection will be populated in the result.

The advantage of this method is that the filtering is performed in the database rather than returning all results to your application and then doing the filtering - which is the behaviour of DistinctRootEntityTransformer.

like image 82
Aidan Boyle Avatar answered Sep 18 '22 12:09

Aidan Boyle


Cannot see the forum post at this moment (broken link?), so maybe this is not the answer, but you can add a DistinctRootEntityResultTransformer:

session.CreateCriteria(typeof(Product)     .Add(...)     .SetResultTransformer(new DistinctEntityRootTransformer()) 
like image 23
Juanma Avatar answered Sep 17 '22 12:09

Juanma