How to execute the following SQL-Query using LINQ or HQL
How can I execute the following query using Castle ActiveRecords and LINQ or HQL?
SELECT a.id, s.classes, COUNT(p.id), MAX(p.date) AS last, MIN(p.date) AS first
FROM account a LEFT JOIN school s ON s.account_id = a.id LEFT JOIN user u ON u.account_id = a.id LEFT JOIN points p ON p.user_id = u.id WHERE payment = "S" GROUP BY a.id
The tables are related in the following way:
I also have ActiveRecord classes for all tables with the correct relations defined (if I do the query in steps it works, but it is slow as there are a lot of rows) and I tried the following which didn't worked:
var result = from account in AccountRecord.Queryable
join s in SchoolRecord.Queryable on account equals s.Account into schools
from school in schools.DefaultIfEmpty(null)
join user in UserRecord.Queryable on account equals user.Account
join p in PointsRecord.Queryable on user equals p.User into points
where account.PaymentType == "S"
select new { Account = account, School = school开发者_Python百科, Count = points.Count() };
which threw the following The method or operation is not implemented
-Exception at:
NHibernate.Linq.Visitors.QueryModelVisitor.VisitGroupJoinClause(GroupJoinClause groupJoinClause, QueryModel queryModel, Int32 index)
Found the solution using HQL - I'm still open for a LINQ solution:
HqlBasedQuery query = new HqlBasedQuery(typeof(AccountRecord),
"SELECT a, s, COUNT(p), MIN(p.DateUTC), MAX(p.DateUTC) " +
"FROM AccountRecord a " +
"LEFT JOIN a.Schools s " +
"LEFT JOIN a.Users u " +
"LEFT JOIN u.Points p " +
"WHERE a.PaymentType=:payment GROUP BY a.Id");
query.SetParameter("payment", "S");
var result = from object[] row in (ArrayList)ActiveRecordMediator.ExecuteQuery(query)
select new
{
Account = row[0] as AccountRecord,
School = row[1] as SchoolRecord,
Count = row[2],
First = (new DateTime(1970, 1, 1, 0, 0, 0, 0)).AddSeconds(Convert.ToDouble(row[3])),
Last = (new DateTime(1970, 1, 1, 0, 0, 0, 0)).AddSeconds(Convert.ToDouble(row[4]))
};
I think your Linq query would be something like:
var result = from a in AccountRecord.Queryable
join s in SchoolRecord.Queryable on a.id equals s.account_id
join u in UserRecord.Queryable on a.id equals u.account_id
join p in PointsRecord.Queryable on u.id equals p.user_id
where a.payment == "S"
group by a.id
select new
{
Account = a,
School = s,
Count = p.Count()
};
Though I'm not sure how well NHibernate will handle the group by
and Count()
combination. You might want to see what the generated SQL ends up being, if it doesn't throw an error.
If that doesn't work, you might want to select the records back, and group/count them in the application instead, more like:
var data = from a in AccountRecord.Queryable
join s in SchoolRecord.Queryable on a.id equals s.account_id
join u in UserRecord.Queryable on a.id equals u.account_id
join p in PointsRecord.Queryable on u.id equals p.user_id
where a.payment == "S"
select new
{
Account = a,
School = s,
Count = c
};
var grouped = data.ToList.GroupBy(x => x.Account.Id);
精彩评论