2014-09-22 5 views
0

IQueryable<T>.Select 문에서 사용자 정의 메소드를 실행해야합니다.IQueryable의 사용자 정의 메소드 <T>. 선택

query.Select(r => new ResultObject() 
{ 
Id = r.Persion.Id, 
Code = r.Person.Code, 
CalculatedField = CalculateField(r.Person) 
} 

문제는 linq-to-sql 예외가 발생하므로 문제가 발생합니다.

private static CalcFieldEnum CalculateField(Person p) 
{ 
    if(p.Age < 21) 
    { 
     if(p.Salary > 2000 && p.YearsWorked > 2) 
      return CalcFieldEnum.TypeB; 
     else if(p.YearsWorked <= 2) 
      return CalcFieldEnum.TypeC; 
    } 
    else 
    { 
     if(p.Salary > 3000) 
      return CalcFieldEnum.TypeB; 
    } 

    return CalcFieldEnum.TypeA; 
} 

방법 (CalculateField)에 대한 중요한 유일한 것은 그냥 어떤 실체를 받아 반환이 개체의 필드 값을 기준 및 결과이다 : CalculateField는 기본적으로 스위치 문입니다.

사용자가 결과를 열별로 정렬하고 IQueryable에서 정렬을 실행할 수 있기 때문에이 메서드 포스트 쿼리를 실행할 수 없습니다. 이 문제를 해결할 수있는 방법이 있습니까?

P.S 나는 실제로 그 경우-else 문을 많이 더 이 있으며, 방법의 논리를 단순화. 아이디어는 동일하지만, 단지 객체의 필드를 기반으로하는 enum 값을 반환합니다.

답변

0

당신은 당신이 원하는 어떤 방법을 사용하는 DB에서 가져 오기 및로드 기록에 AsEnumerable 방법을 사용할 수 있습니다 :

query.AsEnumerable().Select(...); 
+0

위대한, 정렬 문제 (정렬 필드 이름) 있지만 해결할 수 있습니다. 내 주요 관심사는 성능입니다. 로컬에서 정렬을 수행하면 성능에 문제가 있습니까? – Arnthor

+0

DB에있는 레코드 수에 따라 다릅니다. 이와 같은 상황에서 저는 보통 DB에서 필터링을 수행하고 결과를 가져와 다른 _unsupported_ 연산을 메모리에서 수행합니다. 당신의 경우에는 너무 중요하지 않아야한다고 생각합니다. 어쨌든 레코드를 가져올 것입니다. –

2

: 한 번보세요

p => p.Age < 21 
    ? (
     (p.Salary > 2000 && p.YearsWorked > 2) 
      ? CalcFieldEnum.TypeB 
      : (p.YearsWorked <= 2 ? CalcFieldEnum.TypeC : CalcFieldEnum.TypeA) 
    ) 
    : (p.Salary > 3000 ? CalcFieldEnum.TypeB : CalcFieldEnum.TypeA); 

그러면 데이터베이스에 전달할 수 있습니다.

+0

죄송 합니다만, if-else 문이 아주 길어서 3 진 연산자로 다시 쓰면 읽을 수없는 혼란이 생기는 것을 언급하지 않았습니다. – Arnthor

+1

@Arnthor 글쎄, 읽을 수없는 혼란과 그것을 실행 (그리고 후속 정렬) 사이에 tossup이야, 그럼. – Rawling

+1

큰 세트에서 로컬로 정렬하는 것에 대한 조언을 원하십니까? – Arnthor