我试图弄清楚如何将这样的复杂查询转换为编译查询并保持代码干净。这个不是那么复杂,但它是一个例子,我有更复杂的查询。
所以我想转换这个投影查询:
public List<GetAnswers> GetAnswers(int pQuestionId, string pSearch, int? pSkip, int? pTake, GetAnswersOrderBy pOrderBy, bool pOrderByIsAscending, out int pTotalNumberOfLines)
{
string search = pSearch.ToUpper().Replace(" ", "");
string languageCode = Thread.CurrentThread.CurrentCulture.ToString().ToLower().Substring(0, 2);
IQueryable<Answer> query = this.Context.Set<Answer>();
//Filter question by questionnaire
query = query.Where(w => w.QuestionID == pQuestionId);
if (!string.IsNullOrEmpty(pSearch))
query = query.Where(w => (w.AnswerTranslations.Any(a => languageCode == a.LanguageCode)
? w.AnswerTranslations.FirstOrDefault(a => languageCode == a.LanguageCode).Label
: w.AnswerTranslations.OrderBy(o => o.Language.Priority).FirstOrDefault().Label)
.ToUpper().Replace(" ", "")
.Contains(search));
switch (pOrderBy)
{
case GetAnswersOrderBy.CorrectAnswer:
query = pOrderByIsAscending ? query.OrderBy(w => w.CorrectAnswer) : query.OrderByDescending(w => w.CorrectAnswer);
break;
case GetAnswersOrderBy.ResponseCount:
query = pOrderByIsAscending ? query.OrderBy(w => w.ResponseCount) : query.OrderByDescending(w => w.ResponseCount);
break;
default:
break;
}
pTotalNumberOfLines = query.Count();
var pagedQuery = query.Skip(pSkip ?? 0)
.Take(pTake ?? pTotalNumberOfLines);
var projectedQuery = pagedQuery.Select(s =>
new
{
Answer = s,
s.AnswerTranslations,
AnswerTranslationsLanguages = s.AnswerTranslations.Select(qt => qt.Language),
}).ToList();
return projectedQuery.Select(s => new GetAnswers()
{
Id = s.Answer.Id,
Label = s.Answer.Label,
CorrectAnswer = s.Answer.CorrectAnswer,
Feedback = s.Answer.Feedback,
Weighting = s.Answer.Weighting
}).ToList();
}
像这样保持代码干净:
public List<Answer> GetAnswers(int pQuestionId, string pSearch, int? pSkip, int? pTake, GetAnswersOrderBy pOrderBy, bool pOrderByIsAscending, out int pTotalNumberOfLines)
{
var compiledQuery = CompiledGetAnswers(params...);
var projectedQuery = compiledQuery .Select(s =>
new
{
Answer = s,
s.AnswerTranslations,
AnswerTranslationsLanguages = s.AnswerTranslations.Select(qt => qt.Language),
}).ToList();
return projectedQuery.Select(s => new GetAnswers()
{
Id = s.Answer.Id,
Label = s.Answer.Label,
CorrectAnswer = s.Answer.CorrectAnswer,
Feedback = s.Answer.Feedback,
Weighting = s.Answer.Weighting
}).ToList();
}
public static Func<AppDbContext, Answer, IQueryable<Answer>> CompiledGetAnswers(int pQuestionId, string pSearch, int? pSkip, int? pTake, GetAnswersOrderBy pOrderBy, bool pOrderByIsAscending, out int pTotalNumberOfLines)
{
string search = pSearch.ToUpper().Replace(" ", "");
string languageCode = Thread.CurrentThread.CurrentCulture.ToString().ToLower().Substring(0, 2);
IQueryable<Answer> query = this.Context.Set<Answer>();
//Filter question by questionnaire
query = query.Where(w => w.QuestionID == pQuestionId);
if (!string.IsNullOrEmpty(pSearch))
query = query.Where(w => (w.AnswerTranslations.Any(a => languageCode == a.LanguageCode)
? w.AnswerTranslations.FirstOrDefault(a => languageCode == a.LanguageCode).Label
: w.AnswerTranslations.OrderBy(o => o.Language.Priority).FirstOrDefault().Label)
.ToUpper().Replace(" ", "")
.Contains(search));
switch (pOrderBy)
{
case GetAnswersOrderBy.CorrectAnswer:
query = pOrderByIsAscending ? query.OrderBy(w => w.CorrectAnswer) : query.OrderByDescending(w => w.CorrectAnswer);
break;
case GetAnswersOrderBy.ResponseCount:
query = pOrderByIsAscending ? query.OrderBy(w => w.ResponseCount) : query.OrderByDescending(w => w.ResponseCount);
break;
default:
break;
}
pTotalNumberOfLines = query.Count();
var pagedQuery = query.Skip(pSkip ?? 0)
.Take(pTake ?? pTotalNumberOfLines);
return CompiledQuery(AppDbContext db, Answer a) => pagedQuery;
}