2016-07-28 8 views
-3

IQueryable을 반환하는 함수에서 2 테이블 조인이 있다고 가정하지만 출력은 두 테이블 중 하나도 아닌 명명 된 형식입니다 테이블 :필드가 선택된 출력에 없을 때 Where()를 IQueryable에 추가 할 수 있습니까?

var qry = from p in Persons 
      join h in Hobbies on p.PersonId equals h.PersonId 
      select new OutputType 
      { 
       Name = p.FirstName, 
       Hobby = h.HobbyName 
      } 

return qry 

이의 말을하자 지금 내가 좋아하는 뭔가를이 쿼리 반환 타고 싶었던 : 당신이 된 IQueryable 유형의 OutputType의 때문에이 문제가 볼 수있는, 내가 할 수있는

var newQuery = qry.Where(p=>p.Age > 18) 

나이를 OutputType에 추가하지 않으면 사람의 나이에 어디를 추가 할 수 없습니다.

어쨌든 IQueryable 표현식 트리를 손상시키고 거기에 지정된 소스 컬렉션에 대해 쿼리하고 Where 절을 추가하는 lambda를 추가합니까? 아니면 궁극적으로 그것을 투영에 무관심한 경우에도 OutputType에 Where 필드를 추가해야합니까?

+3

정말로 원한다면 할 수있는 방법을 찾을 수 있다고 생각하지만 실제로는 디자인에 결함이 있다는 신호 일 뿐이며 이전에 필터링을 수행하는 등 코드를 구조화해야합니다. 시퀀스를 투영합니다. – Servy

+0

어쩌면 조금 재 설계하고'Persons'의 값을 전달할 수 있습니다. 그래서'Persons' 대신'Persons.Where (p => p.Age> 18)' –

+0

에 전달할 것입니다. 제가 준 예제는 바로 그 예입니다. 나는 그 개념을 보여 주려 한 것이지 사용법은 보이지 않았다. 실제 사례는 기존 레거시 Oracle 데이터베이스 위에 4 테이블 조인입니다. 동일한 (대형) 쿼리의 3 가지 변형이 있으며, 다른 테이블의 비 예상 값에 대한 Where 절만 다릅니다. 여러 개의 큰 LINQ 쿼리를 유지하지 않도록 코드의 중복을 줄이려고합니다. 아래의 첫 번째 답변은 필드를 초기에 추가하고 궁극적으로 예상하지 않는 경우 벌칙이 부과되지 않는다는 점에서 매우 유용합니다. 유일한 단점은 여러 개의 새로운 유형을 만들어야한다는 것입니다. –

답변

1

역 추적하려고 시도하는 것보다 나중에보기를 좁히는 것이 더 쉽습니다. 다음은 재사용을 위해 메서드를 계층화하여 멋진 SQL을 추출하는 방법을 보여주는 예제입니다.

private IQueryable<Part> GetParts_Base() 
{ 
    //Proprietary. Replace with your own. 
    var context = ContextManager.GetDbContext(); 

    var query = from c in context.Component 
       where c.Active 
       //kind of pointless to select into a new object without a join, but w/e 
       select new Part() 
       { 
        PartNumber = c.ComponentNumber, 
        Description = c.ComponentDescription, 
        Cost = c.ComponentCost, 
        Price = c.ComponentPrice 
       }; 

    return query; 
} 

//Exclude cost from this view 
public IEnumerable<Part_PublicView> GetParts_PublicView(decimal maxPrice) 
{ 
    var query = GetParts_Base(); 

    var results = from p in query 
        where p.Cost < maxPrice 
        select new Part_PublicView() 
        { 
         PartNumber = p.PartNumber, 
         Description = p.Description, 
         Price = p.Price 
        }; 

    return results; 
} 

public class Part_PublicView 
{ 
    public string PartNumber { get; set; } 
    public string Description { get; set; } 
    public decimal Price { get; set; } 
} 

private class Part : Part_PublicView 
{ 
    public decimal Cost { get; set; } 
} 

Linq-to-entity는 추가 열을 일찍 선택하면 불이익을주지 않습니다. 보시다시피 SQL에는 제약 조건의 비용 열이 포함되어 있지만 선택 항목에는 포함되지 않습니다.

SELECT 
    1 AS [C1], 
    [Extent1].[ComponentNumber] AS [ComponentNumber], 
    [Extent1].[ComponentDescription] AS [ComponentDescription], 
    [Extent1].[ComponentPrice] AS [ComponentPrice] 
FROM [dbo].[Component] AS [Extent1] 
WHERE [Extent1].[ComponentCost] < @p__linq__0 
+0

유일한 네거티브는 각 레이어에 대해 이러한 모든 명명 된 유형을 만드는 것이지만 사용자가 준 응답은 매우 견고합니다. 실제로 IQueryable의 비트가 메서드 반환시 액세스하기가 너무 어렵다는 점이 유감이지만이 경우도 의심 스럽습니다. 감사! –