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>();
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.
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.
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 ();
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.
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>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With