LINQ 확장 메서드가있는 여러 WHERE 절


79

다음과 같은 LINQ 쿼리가 있습니다.

DateTime today = DateTime.UtcNow;
var results = from order in context.Orders
              where ((order.OrderDate <= today) && (today <= order.OrderDate))
              select order;

LINQ를 배우고 이해하려고합니다. 어떤 경우에는 두 개의 추가 WHERE 절을 추가해야합니다. 이를 위해 다음을 사용하고 있습니다.

if (useAdditionalClauses)
{
  results = results.Where(o => o.OrderStatus == OrderStatus.Open)  // Now I'm stuck.
}

보시다시피 WHERE 절을 추가하는 방법을 알고 있습니다. 하지만 여러 개를 어떻게 추가합니까? 예를 들어, 나는 추가하고 싶습니다

WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID

내 이전 쿼리에. 확장 메서드를 사용하여 어떻게합니까?

감사합니다!

답변:


151

두 가지 방법:

results = results.Where(o => (o.OrderStatus == OrderStatus.Open) &&
                             (o.CustomerID == customerID));

또는:

results = results.Where(o => (o.OrderStatus == OrderStatus.Open))
                 .Where(o => (o.CustomerID == customerID));

나는 보통 후자를 선호합니다. 그러나 SQL 서버를 프로파일 링하여 쿼리 실행을 확인하고 어떤 것이 데이터에 대해 더 나은지 확인하는 것이 좋습니다 (차이가있는 경우).

.Where()메서드 연결에 대한 참고 사항 : 원하는 모든 LINQ 메서드를 함께 연결할 수 있습니다. 같은 메소드 .Where()는 실제로 데이터베이스에 대해 실행되지 않습니다 (아직). 이들은 실행을 지연 실제 결과 (예와 같이 계산 될 때까지 .Count()또는 .ToList()). 따라서 여러 메서드를 함께 연결하면 ( .Where(), .OrderBy()또는 그 효과에 대한 더 많은 호출 등) 표현식 트리 라는 것을 구축합니다 . 이 전체 트리는 평가할 때가되면 데이터 소스에 대해 실행되는 것입니다.


2
내가 할 수 있을지 모를 멍청한 기분이야 .. 당신은 너무 많은 스파게티 코드에서 날 구해 줬어요.
ledgeJumper 2014

감사합니다. 도움이되었습니다. 그러나 특정 변수에 따라 where 절 중 하나를 트리거 할 수도 있습니까? @ 데이비드
무하마드 Ashikuzzaman

끝에 select 절과 함께 사용할 수 있습니까?

@New_Coder : 물론입니다. .Where () 절은 반환 유형을 변경하지 않습니다.
David

내가 이것을 할 때 이상하게 : List <string> paths = db.ClientStatement_Inventory .Where (x => (x.statementYear == yea)) .Where (x => (x.statementMonth == mon)) .Select ( c => c.statementPath) .ToList (); 작동하지 않습니다. 하지만 where 절이 1 개만 있으면 내 databse를 쿼리합니다.

24

한 것처럼 계속 연결할 수 있습니다.

results = results.Where (o => o.OrderStatus == OrderStatus.Open);
results = results.Where (o => o.InvoicePaid);

이것은 AND를 나타냅니다.


당신과 다른 사람들도 저를 이겼습니다. 그러나 이것은 아마도 가장 읽기 쉬운 방법입니다.
Schroedingers Cat 2012 년

5
사이에 "and"연산자를 사용하여 쿼리에 절이 추가되는 위치를 반복합니다.
링커로

이것은 아마도 '가장 깨끗한'솔루션은 아니지만 제 경우에는 지금까지 작동 한 유일한 솔루션입니다. UI의 선택에 따라 'where'절을 추가해야했습니다.
DJ van Wyk

1
Where 's가 "OR"로 지정되도록하는 방법이 있습니까?
EK_AllDay

11

메모리 내 데이터 ( "POCO 컬렉션"읽기)로 작업하는 경우 다음과 같이 PredicateBuilder를 사용하여 식을 함께 스택 할 수도 있습니다 .

// initial "false" condition just to start "OR" clause with
var predicate = PredicateBuilder.False<YourDataClass>();

if (condition1)
{
    predicate = predicate.Or(d => d.SomeStringProperty == "Tom");
}

if (condition2)
{
    predicate = predicate.Or(d => d.SomeStringProperty == "Alex");
}

if (condition3)
{
    predicate = predicate.And(d => d.SomeIntProperty >= 4);
}

return originalCollection.Where<YourDataClass>(predicate.Compile());

언급 된 전체 소스는 다음과 같습니다 PredicateBuilder(하지만 몇 가지 예를 더 포함 하여 원본 페이지 를 확인할 수도 있습니다 ).

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  public static Expression<Func<T, bool>> False<T> () { return f => false; }

  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }

  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                                       Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  }
}

참고 : 이식 가능한 클래스 라이브러리 프로젝트 에서이 접근 방식을 테스트 .Compile()했으며 작동 하도록 사용해야 합니다.

Where (predicate .Compile () );


이것이 Entity Framework LINQ에서 작동하지 않는 이유가 있습니까?
Ciantic

나에게도 EF Core와 잘 작동합니다. 결과 술부는 SQL로 올바르게 변환됩니다.
Thomas Hilbert

5

확실히:

if (useAdditionalClauses) 
{ 
  results = 
    results.Where(o => o.OrderStatus == OrderStatus.Open && 
    o.CustomerID == customerID)  
} 

또는 다음 .Where()과 같은 또 다른 호출 (다른 부울 제어 변수로 분할되지 않는 한 왜 원하는지 모르겠지만) :

if (useAdditionalClauses) 
{ 
  results = results.Where(o => o.OrderStatus == OrderStatus.Open).
    Where(o => o.CustomerID == customerID);
} 

또는 다른 재 할당 results:`results = results.Where ( blah ).


2

&&를 사용하고 모든 조건을 동일한 where 절에 쓰거나 .Where (). Where (). Where () ... 등을 할 수 있습니다.


1
results = context.Orders.Where(o => o.OrderDate <= today && today <= o.OrderDate)

이미 주문 작업을하고 있으므로 선택이 필요하지 않습니다.


0

&&부울 논리를 수행하는 데 필요한 다른 명령문과 같이 연산자를 사용하십시오 .

if (useAdditionalClauses)
{
  results = results.Where(
                  o => o.OrderStatus == OrderStatus.Open 
                  && o.CustomerID == customerID)     
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.