Reputation: 22273
How to express the query
Select * from
(select name, Max(date) as date from items group by name) as latest
inner join items as i
on i.name=latest.name and i.date = latest.date
in NHibernate's QueryOver syntax?
As a result I expect to get records with maximum dates for each name from items table.
Each item in table correspond to the ItemEnity
class:
[Class(Table = "items")]
public class ItemEnity
{
[Id(Name = "Id")]
[Generator(1, Class = "native")]
public virtual long Id { get; set; }
[Property(NotNull = true)]
public virtual string Name { get; set; }
[Property(NotNull = true)]
public virtual DateTime Date { get; set; }
// other columns ...
}
I've managed to express subquery in a strongly typed form:
public class ItemLatest
{
public string Name { get; set; }
public DateTime Date { get; set; }
}
// ...
ItemLatest latest = null;
var subquery = QueryOver.Of<ItemEntity>().SelectList(list => list
.SelectGroup(i => i.Name).WithAlias(() => latest.Name)
.SelectMax(i => i.Date).WithAlias(() => latest.Date))
.TransformUsing(Transformers.AliasToBean<ItemLatest>());
var result = subquery.GetExecutableQueryOver(session).List<ItemLatest>();
But I have no clue how to write join because I can't find out how to use JoinQueryOver()
to express connection between two entities (ItemLatest and ItemEnity in my case) that has no relation property referencing from one to another.
Upvotes: 0
Views: 1800
Reputation: 123861
The JOIN is in the ORM world (including NHibernate) defined by mapping. So, if you would like to use criteria and JOIN, it must be over the Referenced property.
What we could for example do, is to create a new object e.g. ItemEnityMaxDate
and map it to view similar to your SELECT MAX .. GROUP BY. We can extend it like this for example:
SELECT main.Id, main.Name, main.Date
FROM items main
INNER JOIN
(
SELECT i.Name, Max(i.Date) AS Date FROM items i GROUP BY i.Name
) AS latest
ON main.Name = latest.Name AND main.Date = latest.Date
The C# ItemEnityMaxDate
would be similar as ItemEntity
(well we will need only Id), mapped to the above view.
Then we can use it as a subquery
// inner select
var subquery = DetachedCriteria.For<ItemEnityMaxDate>()
.SetProjection(Projections.Property("Id"));
// the ItemEntity
var query = session.CreateCriteria<ItemEntity>()
.Add(Subqueries.PropertyIn("Id", subquery));
var list = query.List<ItemEntity>();
This is probably not the only way. But this way, having your "special query" represented as an object ... would work
Upvotes: 1