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 th
I also ran into the problem of the non-distinct number of items (I use a fetch="join" in my mapping file). I used Linq To Nhibernate to solve the problem, which is used in the following way:
var suppliers = (from supplier in session.Linq<Supplier>()
from product in supplier.Products
where product.Category.Name == produtCategoryName
select supplier).ToList().Distinct();
For what it is worth, NHibernate: Optimising Queries with Projections helped me with basically this same issue.
We are using the most modern and powerful and impressively tiny means of all to handle this...read on only if you're prepared for the awesome...and it has NOTHING to do with criteria...
CurrentSession()
.QueryOver<GoodBadAndUgly>
.Where(...)
.TransformUsing(Transformers.DistinctRootEntity)
So, if you've come here hoping for a way to do this that has you avoiding messing with Criteria even though you though you would totally have to go in that direction just to add 'DISTINCT' into your SQL...search no further
Simplier and better. In case You want to get a whole Entity with DISTINCT you can use Projections.Entity
Criteria.SetProjection(
Projections.Distinct(Projections.Entity(typeof(YourEntityHere), "this")));
"this" means root entity.
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())
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.