2014-11-10 2 views
4

이 두 쿼리의 차이점은 무엇입니까?Linq 올바르게 사용하는 방법

동일하지 않으며 어느 것이 신속합니까? 어디에 문제가있을 것입니까? 어디에서 코드를 작성하면 내 코드를 읽을 수있게됩니다. 내가 잘못 했니?

먼저 쿼리

Model= (model.Where(p => p.Date.Year == yilim) 
         .Where(p => p.Id== 2 || p.Id== 3) 
         .OrderBy(m => m.Date.Month)) 
         .ToList(); 

번째 질의 :

Model= (model.Where(p => p.Date.Year == yilim && (p.Id== 2 || p.Id== 3)) 
          .OrderBy(m => m.Date.Month)) 
          .ToList(); 

답변

5

는 더 기능 차이가 없습니다, 당신은 두 개의 별도의 조건 함께 물건을 보내고 현재 AND 있습니다.

그러나 컴파일러가 단락과 같은 조건 검사를 최적화하는 기능과 두 번째 Where에 필요한 추가 열거자를 제거하는 기능면에서 다소 비효율적입니다. (사과는, 그 부분은 객체 만 Linq에 대한이었다.)

당신의 코드 만 두 번째 쿼리 당신이 원하는 것을 제공 할 조건을 OR했다 경우

Model= (model.Where(p => p.Date.Year == yilim || p.Id== 2 || p.Id== 3) 
          .OrderBy(m => m.Date.Month)) 
          .ToList(); 

// Cannot express the above query in simple daisy-chained Where calls. 

만약 Where의 논리 "주석이없는 코딩"을 시도하고 매우 읽기 쉬운 이름을 가진 메소드에 조건을 채우기가 어려우면 .Where(x => TheCustomerNameIsValid(x))을 수행하거나 .Where(TheCustomerNameIsValid) (가능한 경우)을 그룹화하는 방법을 사용할 수 있습니다. 메소드에 중단 점을 배치하는 것이 람다 (lambda)에서하는 것보다 약간 덜 까다 롭기 때문에 디버깅에도 도움이됩니다.

+0

와우 나는 많은 경험을 쌓은이 후반을 배우고 있습니다. 이 표현식에서 읽을 수있는 이름을 가진 함수를 사용하는 것은 GENIUS입니다. –

+0

@IsThatSo 나의 풍자 경보가 울리고있다 ... Lol –

+1

하하 그것은 영국인에게 칭찬을 지불하기 어렵다 :) –

3

차이가 제 쿼리 시퀀스라는 모델에 생성 된 시퀀스에 적용되는 곳에 제 될 것이라는 것이다 두 번째 방법을 적용했습니다. 두 번째 쿼리에서 Where 메서드는 model이라는 시퀀스에 적용됩니다. 즉, 두 번째 쿼리는 모델 시퀀스를 한 번만 실행하기 때문에 첫 번째 쿼리보다 두 번째 쿼리가 더 효율적입니다.

그러나 두 번째 단계는 이론에서보다 효율적인 단계라고 나와 있습니다. 나는 실제적으로 측정 할 수있는 차이가 있다면 중요하다고 생각하지는 않습니다. 데이지 체인 Where 전화 논리 AND 작동하기 때문에

2

둘 사이에 중요한 성능 차이가 있음을 눈치 채지 못할 것입니다. Where()을 두 번 호출하면 약간의 오버 헤드가 추가됩니다. 추가 중간 개체를 만들고 열거하는 동안 처리 할 추가 메서드 호출이 있습니다.

하지만 대부분의 코드에서 이러한 차이는 눈에 띄지 않습니다. 필터를 두 개의 별도 호출 인 Where()으로 분할하여 코드를 읽고 유지 관리하는 것이 쉬운 경우 더 나은 방법입니다.

적어도, 즉, 할 때까지 실제 성능 문제가 있습니다. 그런 다음 다시 돌아가서 이것이 문제의 일부인지 여부와 재검토 가치가 있는지 다시 확인할 수 있습니다.

2

기타 답변은 답변을 매우 명확하게하지만 다른 권장 사항이 있습니다. 디버깅을 통해 결과 SQL 쿼리를 체크 아웃하지 않는 이유는 무엇입니까? 그들 사이에 차이가 있는지 보게 될 것입니다.

using (EntityConnection con = new EntityConnection("Name = testEntities")) 
{ 
    con.Open(); 

    using (testEntities db = new testEntities()) 
    { 
     int yilim = 2013; 

     IQueryable<Model> models = (db.Model.Where(p => p.Date.Year == yilim) 
              .Where(p => p.ID == 2 || p.ID == 3) 
              .OrderBy(m => m.Date.Month)) 
              .AsQueryable(); 

     string modelsQuery = ((System.Data.Objects.ObjectQuery)models).ToTraceString(); 

     IQueryable<Model> models2 = (db.Model.Where(p => p.Date.Year == yilim && 
                 (p.ID == 2 || p.ID == 3)) 
              .OrderBy(m => m.Date.Month)) 
              .AsQueryable(); 

     string modelsQuery2 = ((System.Data.Objects.ObjectQuery)models2).ToTraceString(); 

     System.IO.File.WriteAllText(@"C:\Users\username\Desktop\queries.txt", 
      "Query 1:\r\n" + modelsQuery + "\r\n" + 
      "Query 2:\r\n" + modelsQuery2); 

    } 

을 그리고 그 결과는 다음과 같습니다 : 다음과 같이 쓸 수 있습니다 시스템에서 생성 및 실행 실제 SQL 쿼리를 얻으려면

Query 1: 
SELECT 
[Project1].[ID] AS [ID], 
[Project1].[Date] AS [Date] 
FROM (SELECT 
    DATEPART (month, [Extent1].[Date]) AS [C1], 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Date] AS [Date] 
    FROM [dbo].[Model] AS [Extent1] 
    WHERE ((DATEPART (year, [Extent1].[Date])) = @p__linq__0) AND ([Extent1].[ID] IN (2,3)) 
) AS [Project1] 
ORDER BY [Project1].[C1] ASC 


Query 2: 
SELECT 
[Project1].[ID] AS [ID], 
[Project1].[Date] AS [Date] 
FROM (SELECT 
    DATEPART (month, [Extent1].[Date]) AS [C1], 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Date] AS [Date] 
    FROM [dbo].[Model] AS [Extent1] 
    WHERE ((DATEPART (year, [Extent1].[Date])) = @p__linq__0) AND ([Extent1].[ID] IN (2,3)) 
) AS [Project1] 
ORDER BY [Project1].[C1] ASC 

그리고 그들은 동일합니다. 따라서 성능 차이는 여기에 예상되지 않습니다.

2

어디에서 어디서 코드를 작성하면 내 코드를 읽을 수있게됩니다. 내가 잘못 했니?

기타 성능/실제 컴파일 된 혜택에 댓글을했다, 난 단지 코드의 가독성 제안 (종교적인 성격이다, 그래서 grain of salt 그것을 가지고)입니다.

포맷 첫 번째 쿼리 :

Model= (model.Where(p => p.Date.Year == yilim) 
       .Where(p => p.Id== 2 || p.Id== 3) 
       .OrderBy(m => m.Date.Month)) 
       .ToList(); 

내 취향은 가 적용되는 클래스와 메소드를 줄 것입니다.

Model= (model.Where(p => p.Date.Where(d => d.Year == 2014) 
            .Where(d => d.Month == 11)) 
       .Where(p => p.Id== 2 || p.Id== 3) 
       .OrderBy(m => m.Date.Month)) 
       .ToList(); 

Reformattted 두 번째 쿼리 : 다차원 문처럼 보일 수 있습니다

Model= (model.Where(p => p.Date.Year == yilim 
          && (p.Id== 2 || p.Id== 3)) 
       .OrderBy(m => m.Date.Month)) 
       .ToList(); 

쉽게 읽을 수 같은 경우 운영자에, 나는 인라인 모든 관찰 보고서, 모든 AND 연산에를 유지하도록 선택할 별도의 라인.

마지막으로, 나는 일반적으로 변수의 첫 문자와 일치하는 문자로 람다 식 매개 변수를 줄입니다.

그래서 :

Model= (model.Where(p => p.Date.Year == yilim) 

이된다 : 더 복잡한 쿼리의

Model= (model.Where(m => m.Date.Year == yilim) 

, 나는 또한 사용했습니다 : 때로는 단일 문자

query = persons.Where(person => person == ... 
        .Where(person => person.Friends.Where(friend => 

을 함께 연결하기 어려워진다 표현식 전체가 무엇을하고 있는지를 읽을 필요가없는 표현식.

관련 문제