У меня есть это выражение SQL:
SELECT Musclegroups.Name, COUNT(DISTINCT Workouts.WorkoutID) AS Expr1
FROM Workouts INNER JOIN
Series ON Workouts.WorkoutID = Series.WorkoutID INNER JOIN
Exercises ON Series.ExerciseID = Exercises.ExerciseID INNER JOIN
Musclegroups ON Musclegroups.MusclegroupID = Exercises.MusclegroupID
GROUP BY Musclegroups.Name
Так как я работаю над проектом, который использует EF в WCF Ria LinqToEntitiesDomainService, я должен запросить это с помощью LINQ (если это не является обязательным, пожалуйста, сообщите мне).
Я сделал это выражение:
var WorkoutCountPerMusclegroup = (from s in ObjectContext.Series1
join w in ObjectContext.Workouts on s.WorkoutID equals w.WorkoutID
where w.UserID.Equals(userid) && w.Type.Equals("WeightLifting")
group s by s.Exercise.Musclegroup into g
select new StringKeyIntValuePair
{
TestID = g.Select(n => n.Exercise.MusclegroupID).FirstOrDefault(),
Key = g.Select(n => n.Exercise.Musclegroup.Name).FirstOrDefault(),
Value = g.Select(n => n.WorkoutID).Distinct().Count()
});
StringKeyIntValuePair - это просто пользовательский тип сущности, который я создал, чтобы я мог отправить информацию клиенту Silverlight. Кроме того, именно поэтому мне нужно установить для него «TestID», так как он является сущностью и ему нужен.
И проблема в том, что этот запрос linq производит ужасный оператор SQL:
http://pastebay.com/144532
Полагаю, есть лучший способ запроса этой информации, возможно, лучшее выражение linq. Или можно просто как-нибудь запросить простой SQL?
EDIT:
Я понял, что TestID не нужен, потому что другое свойство с именем «Key» (то, по которому я группирую) становится ключом группы, поэтому он также будет ключом. И после этого мой запрос выглядит так:
var WorkoutCountPerMusclegroup = (from s in ObjectContext.Series1
join w in ObjectContext.Workouts on s.WorkoutID equals w.WorkoutID
where w.UserID.Equals(userid) && w.Type.Equals("WeightLifting")
group w.WorkoutID by s.Exercise.Musclegroup.Name into g
select new StringKeyIntValuePair
{
Key = g.Key,
Value = g.Select(n => n).Distinct().Count()
});
Это приводит к следующему SQL: http://pastebay.com/144545
Это выглядит намного лучше, чем предыдущая инструкция sql полуготового запроса linq.
Но достаточно ли это хорошо? Или это граница возможностей LinqToEntities, и если я хочу еще более ясного sql, я должен сделать еще один DomainService, который работает с LinqToSQL или чем-то еще?
Или лучше всего использовать хранимую процедуру, которая возвращает наборы строк? Если да, то есть ли лучший способ сделать это асинхронно, например, простой запрос WCF Ria DomainService?