2017-03-10 6 views
-1

내가 복잡한 쿼리를 컴파일 된 쿼리로 변환하고 코드를 깨끗하게 유지하는 방법을 알아 내려고 시도 중입니다. 이것은 복잡하지는 않지만 그 예는 훨씬 복잡한 쿼리입니다.복잡한 linq 컴파일 쿼리

그래서 나는이 예상 쿼리 변환하고 싶습니다 :

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; 
} 
+0

당신은 거의 그것을하고 있습니다. –

답변

0

난 당신이 깨끗한 무슨 뜻인지 짐작이 "더 읽기"입니다 : 깨끗한 코드를 유지하기 위해 이런 일에

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(); 
} 

을 . 당신은 실제로 그것을하고 있습니다. 그리고 제 제안은 복잡한 쿼리를 메서드에 넣고 의미있는 이름을 지정하는 것입니다. 사람들이 귀하의 요청에 보이지 않는 경우

예를 들어, 그들은 당신이 다음 코드에서 무엇을하고 있는지 이해하지 못할 것은

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)); 

당신은 확장 클래스

public static class MyQueryExtension 
{ 
    public static IQueryable<Answer> SearchAnswersByLanguageCode(this IQueryable<Answer> query, string languageCode, string search) 
    { 
     return 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)) 
    } 
} 

을 만들 수 있습니다 그리고 당신의 코드에서 호출하십시오.

query = query.SearchAnswersByLanguageCode(languageCode, search); 

그런 다음 main 메소드를 깨끗하고 읽기 쉽게 만들 수 있습니다.

public static Func<AppDbContext, Answer, IQueryable<Answer>> CompiledGetAnswers(int pQuestionId, string pSearch, int?  pSkip, int? pTake, GetAnswersOrderBy pOrderBy, bool pOrderByIsAscending, out int pTotalNumberOfLines) 
{ 
    //Do something 
    if (!string.IsNullOrEmpty(pSearch)) 
     query = query.SearchAnswersByLanguageCode(languageCode, search); 

    query = query.GetItOrdered(parameters); 

    //Do something 
}