[c#] AsQueryable ()의 목적은 무엇입니까?

그 목적은 AsQueryable()당신 IEnumerable이 기대할 수있는 메소드를 전달할 수 있도록 하는 것입니까 IQueryable, 아니면 다음 IEnumerable과 같이 표현할 유용한 이유가 IQueryable있습니까? 예를 들어, 다음과 같은 경우에 해당해야합니까?

IEnumerable<Order> orders = orderRepo.GetAll();

// I don't want to create another method that works on IEnumerable,
// so I convert it here.
CountOrders(orders.AsQueryable());

public static int CountOrders(IQueryable<Order> ordersQuery)
{
    return ordersQuery.Count();
}

또는 실제로 다른 작업을 수행합니까?

IEnumerable<Order> orders = orderRepo.GetAll();
IQueryable<Order> ordersQuery = orders.AsQueryable();

IEnumerable<Order> filteredOrders = orders.Where(o => o.CustomerId == 3);
IQueryable<Order> filteredOrdersQuery = ordersQuery.Where(o => o.CustomerId == 3);

// Are these executed in a different way?
int result1 = filteredOrders.Count();
int result2 = filteredOrdersQuery.Count();

IQueryable이러한 확장 메서드 의 버전은 일단 실행되면 동일한 작업을 수행하는 Expression을 구축합니까? 내 주요 질문은 사용에 대한 실제 사용 사례는 AsQueryable무엇입니까?



답변

몇 가지 주요 용도가 있습니다.

  1. 다른 답변에서 언급했듯이 메모리 내 데이터 소스를 사용하여 쿼리 가능한 데이터 소스를 모의하는 데 사용할 수 있으므로 결국 열거 불가능 기반에서 사용될 메서드를 더 쉽게 테스트 할 수 있습니다 IQueryable.

  2. 메모리 내 시퀀스 또는 외부 데이터 소스에 적용 할 수있는 컬렉션을 조작하기위한 도우미 메서드를 작성할 수 있습니다. IQueryable완전히 사용할 도움말 메서드를 작성하는 경우 AsQueryable모든 열거 형에 사용하여 사용할 수 있습니다. 이렇게하면 매우 일반화 된 도우미 메서드의 두 가지 개별 버전을 작성하지 않아도됩니다.

  3. 이를 통해 쿼리 가능의 컴파일 시간 유형을 IQueryable더 파생 된 유형이 아닌 으로 변경할 수 있습니다 . 사실상; 당신은 그것을 사용하는 거라고 IQueryable당신이 사용하는 거라고 같은 시간에 AsEnumerableIEnumerable. 구현하는 객체가있을 수 IQueryable있지만 인스턴스 Select메서드도 있습니다. 이 경우 LINQ Select메서드 를 사용하려는 경우 개체의 컴파일 시간 유형을 IQueryable. 그냥 캐스팅 할 수 있지만 AsQueryable메서드를 사용하면 유형 추론을 활용할 수 있습니다. 이것은 제네릭 인수 목록이 복잡 할 때 더 편리 하고 제네릭 인수가 익명 유형 인 경우 실제로 필요 합니다.


답변

AsQueryable에 대한 가장 유효한 사례는 단위 테스트입니다. 다음과 같은 다소 인위적인 예가 있다고 가정하십시오.

public interface IWidgetRepository
{
   IQueryable<Widget> Retrieve();
} 

public class WidgetController
{
   public IWidgetRepository WidgetRepository {get; set;}


   public IQueryable<Widget> Get()
   {
      return WidgetRepository.Retrieve();
   }
}

컨트롤러가 저장소에서 반환 된 결과를 다시 전달하는지 확인하기 위해 단위 테스트를 작성하고 싶습니다. 다음과 같이 보일 것입니다.

[TestMethod]
public void VerifyRepositoryOutputIsReturned()
{    
    var widget1 = new Widget();
    var widget2 = new Widget();
    var listOfWidgets = new List<Widget>() {widget1, widget2};
    var widgetRepository = new Mock<IWidgetRepository>();
    widgetRepository.Setup(r => r.Retrieve())
      .Returns(listOfWidgets.AsQueryable());
    var controller = new WidgetController();
    controller.WidgetRepository = widgetRepository.Object;

    var results = controller.Get();

    Assert.AreEqual(2, results.Count());
    Assert.IsTrue(results.Contains(widget1));
    Assert.IsTrue(results.Contains(widget2));
}

실제로 모든 AsQueryable () 메서드를 사용하면 mock을 설정할 때 컴파일러를 만족시킬 수 있습니다.

그래도 응용 프로그램 코드에서 이것이 사용되는 곳에 관심이 있습니다.


답변

sanjuro가 언급했듯이 AsQueryable ()의 목적은 Using AsQueryable With Linq To Objects And Linq To SQL에 설명되어 있습니다. 특히 기사는 다음과 같이 말합니다.

이는 T의 IQueryable을 반환하는 엔터티에 특정 메서드가 있고 일부 메서드는 List를 반환하는 실제 단어 시나리오에서 탁월한 이점을 제공합니다. 그러나 컬렉션이 T의 IQueryable 또는 T의 IEnumerable로 반환되는지 여부에 관계없이 모든 컬렉션에 적용해야하는 비즈니스 규칙 필터가 있습니다. 컬렉션은 IQueryable을 구현하고 그렇지 않으면 Linq를 사용하여 메모리에 비즈니스 필터를 적용하여 대리자의 개체 구현에 적용합니다.


답변

AsQueryable ()의 목적은이 기사에서 Linq To Objects 및 Linq To SQL과 함께 AsQueryable 사용하기에서 자세히 설명합니다.

MSDN Queryable.AsQueryable 메서드의 설명 섹션에서 :

소스 유형이 IQueryable을 구현하는 경우 AsQueryable (IEnumerable)은이를 직접 반환합니다. 그렇지 않으면 Queryable에서 대신 Enumerable에서 동등한 쿼리 연산자 메서드를 호출하여 쿼리를 실행하는 IQueryable을 반환합니다.

그것이 바로 위의 기사에서 언급되고 사용 된 것입니다. 귀하의 예에서는 orderRepo.GetAll 반환, IEnumerable 또는 IQueryable (Linq to Sql)에 따라 다릅니다. IQueryable을 반환하면 Count () 메서드가 데이터베이스에서 실행되고 그렇지 않으면 메모리에서 실행됩니다. 참조 된 기사의 예를주의 깊게 살펴보십시오.


답변

인터페이스 IQueryable인용 문서 :

IQueryable 인터페이스는 쿼리 공급자가 구현하기위한 것입니다.

따라서 데이터 구조 .NET에서 쿼리 가능하게 만들려는 사람 에게는 필요하지 않은 데이터 구조 를 열거하거나 유효한 열거자를 가질 수 있습니다 .

IEnumerator대신 데이터 스트림 을 반복하고 처리하기위한 인터페이스입니다 .


답변