2009-11-02 2 views
7

다음과 같은 Linq 쿼리가 있습니다.Linq : 간단한 부울 함수가 linq 예외를 반환합니다.

var query = from x in table where SomeFunctionReturnsBool() select; 

private bool SomeFunctionReturnsBool() 
{ 
    return true; 
} 

"SomeFunctionReturnsBool에 지원되는 변환이 SQL에 없습니다."라는 메시지와 예외가 반환됩니다. 나는 이것이 "SomeFunctionReturnsBool"을 SQL로 평가할 표현식으로 취급하기를 원하기 때문입니다. 그러나 그렇게 할 수는 없습니다.

이 Linq 쿼리는 복잡하지 않지만 실제 쿼리는 복잡합니다. 어떻게해야 할 일을 성취 할 수 있습니까? 이것은 쿼리의 일부를 분해하여 더 읽기 쉽게 만들어주는 것입니다.

제프

업데이트 좋은 답변. 지금 대신 표현식을 사용하려고 노력하고 있지만이 코드는 "메소드를 어디에서 (람다 표현식)을 해결할 수 없습니까?"라고합니다.

var query = from x in table where SomeFunctionReturnsBool() select x; 

private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool 
{ 
    return (x) => true; 
} 
+0

에 사용되는 사용하는 것을 선호합니다. –

답변

7

또 다른 방법은 Expression<Func<YourType, bool>> 술어를 ... 사용하는 것입니다

var query = from x in table where SomeFunctionReturnsBool() select; 

편집 : 나는 보통 그것을 내가 위 한 방법을하지 ... 난 그냥지고 있다고 그 코드에서 위. 여기에 제가 보통 구현하는 방법이 있습니다. 따라서 추가 Enumerable 메서드를 추가하거나 디버깅하는 동안 주석 처리 할 수 ​​있습니다.

var results = table.Where(SomeFunctionReturnsBool()) 
    .OrderBy(yt => yt.YourProperty) 
    //.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts... 
    //.Take(pageSize) 
    .ToList(); //Finally executes the query... 

private Expression<Func<YourType, boo>> SomeFunctionReturnsBool() 
{ 
    return (YourType yt) => yt.YourProperty.StartsWith("a") 
     && yt.YourOtherProperty == true; 
} 

난 당신이 표현을 구축 할 수있는 PredicateBuilder 쿼리 구문이 방법을 사용하는 (모호한) 방식을 보여주는, 댓글에 답글을 올림 당신은 어디 ...

+1

+1입니다. 꽤 괜찮은데. – Tinister

+0

어떤 이유로, 이렇게하면 "어디서 (람다 식)"을 해결할 수 없습니까? – jlembke

+0

아래쪽 투표를 설명 할 시간이 있다면 -2가 왜 좋을지 모르겠다 ... – bytebender

3

당신은 LINQ - 투 - SQL에서이 작업을 수행 할 수 있습니다 데이터 - 컨텍스트; TSQL을 작성하고 ctx.SomeFunctionblah (...)를 사용합니다.

대안은 식 트리로 작업하는 것입니다 - 예를 들어, 수 :

Expression<Func<Customer, bool>> SomeFunc() { 
    return c => true; // or whatever 
} 

.Where(SomeFunc())를 사용 - 충분히 가까이이다?


추가 사기 Where 방법

당신이 쿼리 구문에서 사용할 수있는 방법을 보여줍니다 ...이 경우 쿼리 구문을 사용할 수 있지만 작업 수행 가져옵니다. I 은 환상적이라고 제안하지만 편리 할 것입니다.

using System; 
using System.Linq; 
using System.Linq.Expressions; 

static class Program 
{ 
    static void Main() 
    { 
     using (var ctx = new NorthwindDataContext()) 
     { 
      ctx.Log = Console.Out; 
      // fluent API 
      var qry = ctx.Customers.Where(SomeFunc("a")); 
      Console.WriteLine(qry.Count()); 

      // custom Where - purely for illustration 
      qry = from c in ctx.Customers 
        where SomeFunc("a") 
        select c; 
      Console.WriteLine(qry.Count()); 
     } 
    } 
    static IQueryable<T> Where<T>(this IQueryable<T> query, 
     Func<T, Expression<Func<T, bool>>> predicate) 
    { 
     if(predicate==null) throw new ArgumentNullException("predicate"); 
     return query.Where(predicate(default(T))); 
    } 
    static Expression<Func<Customer, bool>> SomeFunc(string arg) 
    { 
     return c => c.CompanyName.Contains(arg); 
    } 
} 
+0

와우, 멋지다 마크, 나는 이것에 대해 몰랐다. 아래 내 대답을 확인 ... 유용하지만, 이것은 아주 멋지다. 덕분에 – andy

+0

명확히하기 위해, 마크. 표현식 트리를 여기처럼 사용하면 람다 구문을 사용하고 쿼리 구문을 사용해야합니까? – jlembke

+0

니스. 좋아, 나는 그걸로 일할거야. – jlembke

0

쿼리 구문을 사용하지 마십시오.

var query = table.Where(x => SomeFunction(x)); 
+0

LINQ-to-SQL에는 도움이되지 않습니다. 'SomeFunction'에 대한 번역은 아직 없습니다. –

+0

네, 이것과 쿼리 문법 사이에는 아무런 차이가 없습니다. – andy

+0

예, 이것은 동일합니다 .. – jlembke

1

난 그냥 그렇게처럼 그들을 탈옥 것이다 : 당신은 식 트리 주위에 통과 기능을 만들 수

Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true; 

var query = from x in table where someTreeThatReturnsBool select x; 

.

2

"기본적으로"사용자 지정 기능이있는 쿼리를 LINQ-to-SQL에서 실행할 수 없습니다. 사실 SQL로 변환 할 수있는 일부 원시 메소드 만 사용할 수 있습니다.

이 문제를 해결하는 가장 쉬운 방법은 불행히도 DB에서 가져 오는 데이터의 양에 따라 성능에 영향을 미칠 수 있습니다.

기본적으로 데이터가 이미 메모리에로드 된 경우, 즉 SQL이 이미 실행 된 경우에만 WHERE 구문에서 사용자 지정 함수를 사용할 수 있습니다.

귀하의 예를 들어 가장 빠른 수정과 같을 것이다 :

var query = from x in table.ToList() where SomeFunctionReturnsBool() select; 

공지 사항에게 ToList를(). SQL을 실행하고 데이터를 메모리에 저장합니다. 이제 WHERE 문/메서드에서 원하는대로 할 수 있습니다.

+2

참 ... 그렇다면 모든 레코드를 가져 와서 메모리에서 필터링하는 것과 데이터베이스 서버에서 수행하는 것 . – bytebender

+0

동의 함 (J.13.L로) - ToList()를 사용하는 것은 일반적으로 나쁜 방법이며 작은 데이터 볼륨에서만 작동합니다. –

+0

이 모든 것을 뒤로 당기지 않는 것이 좋습니다. 많은 데이터. Andy에게 감사드립니다. – jlembke