How to convert HQL with Group By to QueryOver? - nhibernate

I have a HQL query:
select max(l.Num) from SomeTable l group by l.Type, l.Iteration
How can I translate/convert it to QueryOver?
Following one:
var grouped = session.QueryOver<SomeTable>()
.SelectList(l => l
.SelectGroup(x => x.Type)
.SelectGroup(x => x.Iteration)
.SelectMax(x => x.Num));
will generate SQL:
SELECT
MAX(l.Num),
l.Type,
l.Iteration
FROM
SomeTable l
GROUP BY
l.Type,
l.Iteration
which is not what I expect – I don’t want to have Type and Iteration in Select.
I'm using that query as subquery for select z from c where z IN (subquery).

try with this statement, I've used Aliases and UnderlyingCriteria
SomeTable someTb = null;
var grouped = session.QueryOver<SomeTable>(() => someTb)
.SelectList(l => l.SelectMax(() => someTb.lnum))
.UnderlyingCriteria.SetProjection(
Projections.Group(() => someTb.Type)
,Projections.Group(() => someTb.Iteration))
.List();
I hope it's helpful.

Related

Linq to SQL using Lambda expressions together with Join, GroupBy, Count and Sum

I use this SQL statement to get what I want:
select count(o.Id) as order_amount, sum(r.Price) as Total_ordersum from Orders o join OrderRows r on o.Id = r.OrderId;
I tried this using Linq lambda expression to get the same result:
Orders
.Join(OrderRows, o => o.Id, r => r.OrderId, (o,r) => new {o,r})
.GroupBy(g => new {g.o.Id, g.r.Price})
.Select(group => new {
order_amount = group.Count(),
Total_ordersum = group.Key.Price,
});´
but I get three lines instead of just one with the total order amount and the sum of all orders. What am I doing wrong here?
What am I doing wrong here?
The LINQ and SQL queries are not equivalent. Your SQL query does not have GROUP BY while the LINQ query does group by order Id and record Price, which of course generates different results. Also the SQL query does sum the record Price while LINQ query does not.
You can achieve the same result in LINQ by using a sort of unusual group by constant operator:
var query = Orders
.Join(OrderRows, o => o.Id, r => r.OrderId, (o, r) => new { o, r })
.GroupBy(g => 0) // any constant would work
.Select(g => new
{
order_amount = g.Count(),
Total_ordersum = g.Sum(e => e.r.Price),
});

Multiple Subqueries With QueryOver

I need help converting this sql query into QueryOver Nhibernate criteria.
select distinct * from event e where e.name like '%req%'
or e.Id in (select r.eventId from requirement r where r.name like '%req%')
or e.Id in (select r.eventId from requirement r where r.id
in (select s.requirementId from solution s where s.name like '%sol%'))
var queryOver = session.QueryOver<Event>()
.Where(x => x.Name.IsInsensitiveLike("%"+searchTerms[1]+"%"))
.OrderBy(x => x.CreatedOn).Asc;
So far I have the main query but couldn't find enough reference material on how to add the subqueries. Haven't been successful using joinQueryOver.
Event has one-to-many rel with requirement and requirement has one-to-many rel with solution.
Requirement reqAlias = null;
Solution solAlias = null;
var subQuery = QueryOver.Of<Event>()
.JoinAlias(x => x.Requirements, () => reqAlias)
.Where(x => x.Name.IsInsensitiveLike(searchTerms[2]))
.JoinAlias(() => reqAlias.Solutions, () => solAlias)
.Where(x => x.Name.IsInsensitiveLike(searchTerms[3]))
.Select(Projections.Group<Event>(x => x.Id));
var events = session.QueryOver<Event>()
.Where(x => x.Name.IsInsensitiveLike(searchTerms[1]))
.WithSubquery.WhereProperty(x => x.Id).In(subQuery)
.List().ToList();
still not working.
When you use IsInsensitiveLike NHibernate appends the % after parsing, and uses lower to do a lower case comparison. In your code, you are appending the % yourself, which results in,
select distinct * from event e where e.name like %lower('%req%')%
which in turn, doesn't work.
Also, you have 3 subqueries, no a big one, so you need to restructure your code to account for that:
select r.eventId from requirement r where r.name like '%req%'
to
var firstQuery = QueryOver.Of<Requirement>()
.Where(r => r.Name.IsInsensitiveLike(searchTerms[2]))
.Select(r => r.EventId);
then,
select s.requirementId from solution s where s.name like '%sol%'
to
var solutionQuery = QueryOver.Of<Solution>()
.Where(s => s.Name.IsInsensitiveLike(searchTerms[3]));
then,
select r.eventId from requirement r where r.id
in (select s.requirementId from solution s where s.name like '%sol%')
to
var requirementQuery = QueryOver.Of<Requirement>()
.WithSubquery
.WhereProperty(r => r.Id).In(solutionQuery)
.Select(r => r.EventId);
Then you need to construct the main query using Restrictions.Or to include the 3 queries.

Filtered join with NHibernate QueryOver

Using the Criteria API, I can generate a query that creates a JOIN with an extra condition on the JOIN
var criteria = Session.CreateCriteria<Product>()
.SetReadOnly(true)
.SetMaxResults(1)
.CreateAlias("ProductCategory", "U", JoinType.LeftOuterJoin, Expression.Eq("U.SubType", "Premium"))
.AddOrder(Order.Desc("U.Sequence"));
This generates a JOIN similar to this:
SELECT * FROM dbo.Product w
LEFT JOIN dbo.ProductCategory u
ON u.DefaultProductId = w.Id AND u.SubType = 'Premium'
How do I do the same thing with the QueryOver syntax?
Off the top of my head I think it's like:
ProductCategory category = null;
var result = Session.QueryOver<Product>()
.JoinAlias(x => x.Categories, () => category, JoinType.LeftOuterJoin)
.Where(() => category.SubType == "Premium")
.OrderBy(() => category.Sequence).Desc
.Take(1)
.List();
Edit: Included OrderBy, and gave it a test. Works.
Using the Blog > Posts type example, the generated SQL looks like:
SELECT this_.Id as Id1_1_,
this_.Title as Title1_1_,
post1_.BlogId as BlogId3_,
post1_.Id as Id3_,
post1_.Id as Id3_0_,
post1_.Title as Title3_0_,
post1_.Content as Content3_0_,
post1_.DatePosted as DatePosted3_0_,
post1_.BlogId as BlogId3_0_
FROM [Blog] this_
left outer join [Post] post1_
on this_.Id = post1_.BlogId
WHERE post1_.DatePosted > '2011-11-22T19:43:11.00' /* #p0 */
ORDER BY post1_.DatePosted desc
.JoinAlias has an overload with a withClause
var result = Session.QueryOver<Product>()
.Left.JoinAlias(x => x.Categories, () => category, c => c.SubType == "Premium")
.OrderBy(() => category.Sequence).Desc
.Take(1)
.List();

Convert SQL to LINQ JOIN/GROUP BY/COUNT/DISTINCT

I got a rather tough query to convert from SQL to LINQ-to-Entities.
Here's my SQL code:
select c_id
from db.c
inner join db.i on c_id = i_c
inner join db.l on c_id = l_c
group by c_id
having count(distinct i_attributeX) > count(distinct l_attributeY)
I seem to have problems with the distinct in linq. Any suggestions?
Cheers
How's this:
var result = db.c
.Where(c =>
c.i.Select(i => i.attributeX).Distinct().Count() >
c.l.Select(l => l.attributeY).Distinct().Count()
)
.Select(c => c.id);
or alternatively
var result = db.c
.Where(c =>
c.i.GroupBy(i => i.attributeX).Count() >
c.l.GroupBy(l => l.attributeY).Count()
)
.Select(c => c.id);

QueryOver with Select and OrderBy in NHibernate

I am wondering how do I order a group of results after a select with QueryOver. My query is the following:
CurrentSession.QueryOver<Book>()
.Where(b => b.Author.Name = "SimpleName")
.Select(Projections.Distinct(Projections.Property<Book>(b => b.Genre)))
.OrderBy<Genre>(g => g.Name) // this extension does not exist! How do I order for a Genre?
.List<Genre>()
How can I do?
Your query won't work to begin with. You first of all need to do a join, then you can do your order by and select projections.
Author author = null;
Genre genre = null;
CurrentSession.QueryOver<Book>()
.JoinAlias(b => b.Author, author)
.JoinAlias(b => b.Genre, genre)
.Where(() => author.Name == "SimpleName")
.OrderBy(() => genre.Name)
.Select(Projections.Distinct(Projections.Property<Book>(b => b.Genre)))
.List<Genre>();