2011-05-13 6 views
1

MVC3 웹 사이트. EF4.1 코드 우선.Linq 텍스트 값으로 필터링, 람다가 아닌

정렬 열과 방향을 세션에 저장하므로 사용자가 다시 페이지로 돌아올 때 그리드가 여전히 동일한 정렬 순서로 유지됩니다.

이렇게 저장 한 값으로 컬렉션을 정렬하는 방법을 지정할 수 있기를 원합니다.

this.Issues = this.db.ITIssues.Orderby (this.sort + ""+ this.sortdir) ...

은 현재 내가 switch 문을 사용하여 필드의 모든 다른 조합을 처리해야 + 정렬 방향. 더 좋은 방법이 있습니까?

switch (this.Sort) 
{ 
    case "ITApplication.Name": 
     if (this.SortDir == "ASC") 
      this.Issues = this.db.ITIssues.OrderBy(i => i.ITApplication.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     else 
      this.Issues = this.db.ITIssues.OrderByDescending(i => i.ITApplication.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 

    case "ITIssueType.Name": 
     if (this.SortDir == "ASC") 
      this.Issues = this.db.ITIssues.OrderBy(i => i.ITIssueType.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     else 
      this.Issues = this.db.ITIssues.OrderByDescending(i => i.ITIssueType.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 

    case "CurrentStatus.Name": 
     if (this.SortDir == "ASC") 
      this.Issues = this.db.ITIssues.OrderBy(i => i.CurrentStatus.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     else 
      this.Issues = this.db.ITIssues.OrderByDescending(i => i.CurrentStatus.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 

    case "CurrentAssignedTo.Fname": 
     if (this.SortDir == "ASC") 
      this.Issues = this.db.ITIssues.OrderBy(i => i.CurrentAssignedTo.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     else 
      this.Issues = this.db.ITIssues.OrderByDescending(i => i.CurrentAssignedTo.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 

    case "CreatedBy.Fname": 
     if (this.SortDir == "ASC") 
      this.Issues = this.db.ITIssues.OrderBy(i => i.CreatedBy.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     else 
      this.Issues = this.db.ITIssues.OrderByDescending(i => i.CreatedBy.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 

    case "CurrentPriority.Name": 
     if (this.SortDir == "ASC") 
      this.Issues = this.db.ITIssues.OrderBy(i => i.CurrentPriority.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     else 
      this.Issues = this.db.ITIssues.OrderByDescending(i => i.CurrentPriority.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 

    default: 
     this.Issues = this.db.ITIssues.OrderByDescending(i => i.ID).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 
} 

답변

0

, 첫 번째 this.Sort로 표현되는 문자열에서 속성 이름을 얻는 것을 포함한다. 아마도 반사 코드가 필요할 것입니다. 두 번째 부분은 오름차순 정렬과 내림차순 정렬을 지정하는 데 필요한 코드의 양을 줄이는 것입니다.

여러 가지 방법이 있습니다. 생각한 첫 번째 아이디어는 bool SortDir 인수를 사용하는 OrderBy에 대한 확장 메서드를 만드는 것입니다. OrderBy에는 몇 가지 오버로드가있어 Func<T,TKey> KeySelectors와 IComparer<T>을 허용합니다.

을의 경우 모든없이 코드를 작성할 수, 나는 당신에게 단지 KeySelector에 함께 간단한 보여주지,하지만 당신은 장소에두고 완전히 일반적인 솔루션

public static class IEnumerableExtentions 
{ 
    public static IEnumerable<T> OrderBy<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, bool reverse) 
    { 
     return reverse ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector); 
    } 
} 

그들 모두를 구현할 수 있습니다

switch (this.Sort) 
{ 
    case "ITApplication.Name": 
     this.Issues = this.db.ITIssues.OrderBy(i => i.ITApplication.Name, this.SortDir == "ASC").Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 
    /*...*/ 
} 

정렬 순서를 결정하는 두 번째 방법은 SortDir을 사용하는 IComparer을 전달하는 것입니다. 다음은 그럼 당신은 당신의 코드를 작성하는 좀 더 코드의

switch (this.Sort) 
{ 
    case "ITApplication.Name": 
     this.Issues = this.db.ITIssues.OrderBy(i => i.ITApplication.Name, new ReversableComparer(this.SortDir != "ASC")).Where(i => i.ITAppGroupID == this.ITAppGroupID); 
     break; 
    /*...*/ 
} 

을 쓸 수 있지만, 당신이 그것을 그것의 필요가있는 경우

class ReversableComparer : IComparer<IComparable> 
{ 
    private bool _reverse; 

    public ReversableComparer(bool reverse) 
    { 
     _reverse = reverse; 
    } 

    public int Compare(IComparable x, IComparable y) 
    { 
     return _reverse ? y.CompareTo(x) : x.CompareTo(y); 
    } 
} 

를 사용할 수있는 IComparer 구현입니다.

Linq를 SQL에서 사용하는 경우 속성 이름/리플렉션이 표시되는 한 @AlbertVo에서 제공하는 동적 linq 링크가 유용 할 수 있습니다. Linq with Objects로 더 많은 작업을한다면 i => i.ITApplication.Name 대신 i => i.GetType().GetProperty(this.Sort).GetValue(i, null) 을 시도해보십시오. 물론이 작업을하려면 System.Reflection이 필요하며 원본 솔루션보다 느릴 수 있습니다.

그 중 일부가 도움이 되었기를 바랍니다. 건배.

편집 요약하면,이 두 기술은 결합 될 수 있습니다. 최종 코드는 다음과 같을 수 있습니다.

public static class IEnumerableExtentions 
{ 
    public static IEnumerable<T> OrderBy<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, bool reverse) 
    { 
     return reverse ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector); 
    } 
} 

void Main() 
{ 
    this.Issues = this.db.ITIssues 
     .OrderBy(i => i.GetType().GetProperty(this.Sort).GetValue(i, null), 
      this.SortDir == "ASC") 
     .Where(i => i.ITAppGroupID == this.ITAppGroupID); 
} 
+0

마틴, 훌륭한 제안과 코드에 감사드립니다. 나는 모든 사람들이 동적 인 정렬 순서를 정하기 위해 switch 문을 사용한다고 믿기가 어렵다. 나는 ... linq이 "보이는 것"을 쓰는 두건에서 어떻게 작동하는지에 대해 충분히 알지 못한다. 나는 더 많은 코멘트가있을 때까지 기다릴 것이고, 더 이상 들어 오지 않으면 나는 이것을 답으로 표시 할 것이다. 고마워. – Terrence

+0

@TPSpencer 나는 또한 모든 경우에 .Where (...) 부분이 동일하다는 것을 알아 챘다. Linq가 구성 가능하기 때문에, 당신은 주어진 코드 스 니펫에서 모든 .Where 절을 제거하고 전환 직후에 추가 할당을 할 수있었습니다. 이게 뭔가. 문제 = 이거. 문제. 어디서 (...). –

+0

좋은 지적 마틴, 지적 해 주셔서 고마워. 최종 코드 편집이 유망 해 보입니다. – Terrence

1

나는 최근에 비슷한 것을 해왔습니다. 당신이 찾고있는 것은 Dynamic Linq입니다! 이것 좀보세요 : 코드 두 개의 장애물이있는 것 같습니다

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

+0

나는 어제 그 게시물을 읽었습니다.나는 다른 도서관에 의지 할 필요가 없기를 바랐다. 그리고 아마 linq에 무엇인가 놓치고 있었다. 귀하의 게시물을 가져 주셔서 감사합니다. – Terrence

관련 문제