У меня есть дизайн, в котором мы храним ответы на вопросы сценариев заданных пользователей.Один сценарий может иметь много вопросов, и каждый пользователь может ответить на каждый вопрос несколько раз.
Таблицы MS SQL выглядят (удаляя лишние детали) более или менее примерно так:
-Scripts
ScriptId int (PK, identity)
-ScriptQuestions
ScriptId int (PK)
QuestionId int (PK)
-Questions
QuestionId int (PK, identity)
QuestionText varchar
-Answers
AnswerId int (PK, identity)
QuestionId int
UserId int
AnswerText varchar
Я хотел бы запросить эту базу данных для данного сценария и данного пользователя и получить все вопросы ипоследний ответ предоставляется на каждый вопрос (если есть).В T-SQL я бы сделал что-то вроде этого:
SELECT
sq.QuestionId,
q.QuestionText,
la.AnswerText
FROM
ScriptQuestions sq
ON s.ScriptId = sq.ScriptId
INNER JOIN Questions q
ON sq.QuestionId = q.QuestionId
LEFT OUTER JOIN (
SELECT
QuestionId,
AnswerText
FROM Answers
WHERE AnswerId IN (
SELECT
MAX(AnswerId) LastAnswerId
FROM Answers
WHERE UserId = @userId
GROUP BY QuestionId
)
) la
ON q.QuestionId = la.QuestionId
WHERE
sq.ScriptId = @scriptId
(не проверено, но я думаю, что это близко к тому, что я бы сделал)
Я использую LinqToEF в приложении MVC 3,и чтобы получить те результаты, которые я использовал:
var questions = from sq in script.ScriptQuestions
select new QuestionsAnswers
{
QuestionId = sq.QuestionId,
QuestionText = sq.Question.QuestionText,
LastAnswer = sq.Question.Answers
.Where(a => a.UserId == userId)
.OrderByDescending(a => a.AnswerId)
.Select(a => a.AnswerText)
.FirstOrDefault()
};
И я получаю те же результаты, НО, когда я запускаю профилировщик Intellitrace из VS 2010, я вижу, что linq преобразует это в отправку оператора SELECT
для КАЖДОГОВОПРОС о сценарии, а затем ДРУГОЕ SELECT
утверждение для каждого ответа.Поэтому, если в сценарии содержится 20 вопросов, он будет запрашивать базу данных не менее 40 раз вместо отправки только одного оператора SQL, как указано выше.
Я пытался изменить способ создания оператора LinqToEF, но не смогчтобы преодолеть проблему n SELECT
операторов.
Это не может быть правильным путем или нет?