2012-12-05 2 views
1

안녕하세요. 제 질문에 답변 해 주셔서 감사합니다.동적으로 쿼리 작성

1 년 반 동안 Java로 작업 한 후에 .NET으로 다시 전환하기로 결정했습니다. 나는 VS2012에서 집에 있다고 느낍니다.

Java로 작업하면서 동적 쿼리를 쉽게 생성 할 수있는 최대 절전 모드 구현이 나타났습니다.

5 개의 필드가있는 양식이 있다고 가정 해 봅시다. 결과를 필터링 할 수 있도록 하나의 필드 만 채워야합니다.

if(txtMunicipality.text.length > 0){ 
    (x => x.municipality == txtMunicipality.text) 
} 

if(chkboxIsFinished){ 
    (x => x.isfinished == true) 
} 

등 다음 채워 된 값이 쿼리에 그 기준을 추가하는 경우

그래서 나는 모든 필드 ccheck과 :

나는 C#에서 다음을 수행 할 수있는 방법이있다 .. 그리고 내가 수표로 끝나면 나는 쿼리를 실행한다. C#에서이 작업을 수행 할 수있는 방법이 있습니까?

+0

가 될 수있다 http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query -library.aspx – Habib

+0

동적 LINQ가 아니라 동적으로 쿼리를 작성하는 것이 문제라고 생각합니다. –

+0

네, 맞아요. 내 게시물 – Dragan

답변

1

예, 가능합니다. 가장 간단한 방법은 delegates이며 특히 익명의 방법입니다. - 예제는 여전히 관련되지 않은 경우, 그냥

Func<YourEntity, bool> filter = (_ => true); // Default value. 

if (txtMunicipality.text.length > 0) 
{ 
    filter = (x => x.municipality == txtMunicipality.text); 
} 
else if (chkboxIsFinished) 
{ 
    filter = (x => x.isfinished == true); 
} 

이 그럼 당신은 (내가 의도였다 가정 이는 Where 성명에서 예를 들어, 쿼리에서 filter 대리자를 사용할 수 있습니다 : 예를 들어

) 직접 적용

/ LINQ syntax. 
var entities = from e in context 
       where filter(e) 
       select e; 

// Method syntax. 
var entities = context.Where(x => filter(x)); 
// Or simply: 
var entities = context.Where(filter); 
+0

을 편집 할 것입니다. 'context.Where' 델리게이트를 사용하는 버전은 *** 컨텍스트가 실제로 EF/L2S/NH 등인 경우 ***입니다. 원점이 아닌 .NET 측에서 필터링을 수행합니다. –

+0

흠, 당신 말이 맞아요, 때로는 IQueryable 속성을 잊어 버렸습니다 ... –

2

이 작업을 수행하는 가장 간단한 방법은 즉, 두 개의 쿼리를 작성하는 데

IQueryable<Foo> query = ... // or possibly IEnumerable<Foo> 
if(!string.IsNullOrEmpty(txtMunicipality.text)) { 
    query = query.Where(x => x.municipality == txtMunicipality.text); 
} 
if(chkboxIsFinished) { 
    query = query.Where(x.isfinished); 
} 
입니다

도 표현식 트리 및 대리인을 직접 구성 할 수 있습니다. 필요한 경우 표현 트리와 대리인을 보유하고 있음을 나타냅니다.


편집 : 여기 당신이 표현보다는 쿼리를 구성하는 것을 할 것입니다 방법은 다음과 같습니다 당신이 술어를 결합 할 수 있습니다 몇 가지 유용한 확장 방법을 찾을 수 있습니다이 문서에서

static class Program 
{ 
    static void Main() 
    { 
     Expression<Func<int, bool>> exp1 = x => x > 4; 
     Expression<Func<int, bool>> exp2 = x => x < 10; 
     Expression<Func<int, bool>> exp3 = x => x == 36; 

     var combined = (exp1.AndAlso(exp2)).OrElse(exp3); 
     // ^^^ equiv to x => (x > 4 && x < 10) || x == 36 
    } 
    static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> x, Expression<Func<T, bool>> y) 
    { // trivial cases 
     if (x == null) return y; 
     if (y == null) return x; 

     // rewrite using the parameter from x throughout 
     return Expression.Lambda<Func<T, bool>>(
      Expression.OrElse(
       x.Body, 
       SwapVisitor.Replace(y.Body, y.Parameters[0], x.Parameters[0]) 
      ), x.Parameters); 
    } 
    static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> x, Expression<Func<T, bool>> y) 
    { // trivial cases 
     if (x == null) return y; 
     if (y == null) return x; 

     // rewrite using the parameter from x throughout 
     return Expression.Lambda<Func<T, bool>>(
      Expression.AndAlso(
       x.Body, 
       SwapVisitor.Replace(y.Body, y.Parameters[0], x.Parameters[0]) 
      ), x.Parameters); 
    } 
    class SwapVisitor : ExpressionVisitor 
    { 
     public static Expression Replace(Expression body, Expression from, Expression to) 
     { 
      return new SwapVisitor(from, to).Visit(body); 
     } 
     private readonly Expression from, to; 
     private SwapVisitor(Expression from, Expression to) 
     { 
      this.from = from; 
      this.to = to; 
     } 
     public override Expression Visit(Expression node) 
     { 
      return node == from ? to : base.Visit(node); 
     } 
    } 
} 
1

를 (그것을 작동합니다 NHibernate에 대한뿐만 아니라) :

LINQ to Entities: Combining Predicates

그런 다음 람다를 구축 할 수 있습니다 이 같은 표현 :

Expression<Func<MyObject, bool>> predicate = x => true; 

if(txtMunicipality.text.length > 0){ 
    predicate = predicate.And(x => x.municipality == txtMunicipality.text); 
} 

if(chkboxIsFinished){ 
    predicate = predicate.And(x => x.isfinished == true); 
}