问题
I have the following model:
public class User
{
public virtual int Id { get; set; }
public virtual string Username { get; set; }
public virtual string Password { get; set; }
public virtual string Email { get; set; }
public IList<SubmissionNote> Notes { get;set; }
}
public class SubmissionNote
{
public virtual Int64 Id { get; set; }
public virtual string Text { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual User Creator { get; set; }
public virtual Submission BelongsTo { get; set; }
}
public class Submission
{
public virtual Int64 Id { get; set; }
public virtual DateTime HappenedOn { get; set; }
public virtual int StatusCode { get; set; }
}
I would like to write a query that brings all the Submissions whose last note was entered by some user or a list of users (identified by their names). I would appreciate your help for building this query using NHibernate QueryOver API. I have been able to create a query to bring all the last notes as follows:
SubmissionNote alias = null;
var lastNote = session.QueryOver<SubmissionNote>()
.SelectList(list => list.
SelectGroup(x => x.BelongsTo).WithAlias(() => alias.BelongsTo).
SelectMax(x => x.CreatedOn).WithAlias(() => alias.CreatedOn).
Select(x => x.Creator).WithAlias(() => alias.Creator).
Select(x => x.Id).WithAlias(() => alias.Id).
Select(x => x.Text).WithAlias(() => alias.Text))
.TransformUsing(Transformers.AliasToBean<SubmissionNote>())
.List();
Can I use the specified query as a subquery to produce the required result? Or do you suggest another solution?
回答1:
I would try something like this with a subquery (not tested though)
SubmissionNote subNoteAlias = null, subNoteAliasMax =null;
User userAlias = null;
String[] userNames = new[]{"John","Joe"};
var subquery =
QueryOver.Of(() => subNoteAliasMax)
.Where(subNote => subNote.BelongsTo.Id == subNoteAlias.BelongsTo.Id)
.Select(Projections.Max<SubmissionNote>(subNote => subNote.CreatedOn));
var result = session
.QueryOver<SubmissionNote>(() => subNoteAlias)
.WithSubquery.WhereProperty(subNote=>subNote.CreatedOn).Eq(subquery)
.JoinQueryOver(
subNote=>subNote.Creator
,()=>userAlias
,JoinType.InnerJoin
,Restrictions.In(Projections.Property(() => userAlias.Username ), userNames))
.List();
The generated SQL query would (very) roughly look like :
SELECT SubmissionNote.*
FROM SubmissionNote INNER JOIN User
ON SubmissionNote.creatorId = User.userId
AND User.userName in ('john','joe')
WHERE SubmissionNote.CreatedOn = (SELECT MAX(CreatedOn) FROM SubmissionNote snAlias
WHERE snAlias.SubmissionId = SubmissionNote.SubmissionId)
Hope this will help. There might be issues with the subquery returning a date instead of an id. LMK and I will give it a look.
来源:https://stackoverflow.com/questions/14337580/issues-with-nhibernate-queryover-and-subqueries