2010-01-05 2 views
1

저는 Linq를 Sql으로 사용하고 있습니다. (사실은 동적 Linq를 사용하여 where 절, orderby 등의 런타임에 문자열을 전달할 수 있습니다)하지만 몇 가지 다른 결과와 기본 T-SQL이 TOP 키워드를 사용하는지 아니면 BETWEEN을 사용하는지에 따라 달라지는 것 같습니다.Linq에서 SQL을 사용하면 다른 결과를 얻을 수 있습니다.

내가 문제 아래 작은 예에 침입하려고했습니다, 여기에 시나리오의 :

내가 저장소 패턴을 사용하고 있는데 단순히 왼쪽 외부 2 개 테이블을 조인 다음 방법은 가입 할 수 있습니다.

public IQueryable<TestGalleryViewModel> FetchGalleryItems() 
    { 

     var galleryItems = from painting in Gallery 
          join artist in Artists 
           on painting.ArtistID equals artist.ArtistID 

          into paintingArtists 
          from artist in paintingArtists.DefaultIfEmpty() 

          select new TestGalleryViewModel 
          { 

           Id = painting.PaintingID, 
           ArtistName = artist == default(Artist) ? "" : artist.Surname + " " + artist.Forenames, 
          }; 

     return galleryItems; 
    } 

내가 다음 FetchGalleryItems 방법을 사용하는 작은 시험 방법이 있습니다

 var query = respository.Test_FetchGalleryItems().Where("ArtistName.Contains(\"Adams Charles James\")"); 

     var orderedlist = query.OrderBy("ArtistName asc"); 
     var page1 = orderedlist.Skip(0).Take(5); 
     var page2 = orderedlist.Skip(5).Take(5); 

orderedList는 다음과 같은 기본 값을 포함합니다 :

내가 기대하는 것입니다
176 ADAMS Charles James 
620 ADAMS Charles James 
621 ADAMS Charles James 
660 ADAMS Charles James 
683 ADAMS Charles James 
707 ADAMS Charles James 
735 ADAMS Charles James 
739 ADAMS Charles James 
740 ADAMS Charles James 
741 ADAMS Charles James 

. 그러나 PAGE1 당신이 볼 수

707 ADAMS Charles James 
683 ADAMS Charles James 
660 ADAMS Charles James 
621 ADAMS Charles James 
620 ADAMS Charles James 

하지 처음 5 개 항목입니다 포함되어 있습니다. 페이지 2는 PAGE1에 대한 기본 T-SQL 그것이 TOP을 사용하고

SELECT TOP (5) [t3].[PaintingID] AS [Id], [t3].[value] AS [ArtistName] 
FROM (
    SELECT [t0].[PaintingID], 
     (CASE 
      WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(101),'') 
      ELSE ([t2].[Surname] + ' ') + [t2].[Forenames] 
     END) AS [value] 
    FROM [dbo].[Gallery] AS [t0] 
    LEFT OUTER JOIN (
     SELECT 1 AS [test], [t1].[ArtistID], [t1].[Surname], [t1].[Forenames] 
     FROM [dbo].[Artists] AS [t1] 
     ) AS [t2] ON [t0].[ArtistID] = ([t2].[ArtistID]) 
    ) AS [t3] 
WHERE [t3].[value] LIKE '%Adams Charles James%' 
ORDER BY [t3].[value] 

공지 사항입니다 (10)

에 항목 6 인,

707 ADAMS Charles James 
735 ADAMS Charles James 
739 ADAMS Charles James 
740 ADAMS Charles James 
741 ADAMS Charles James 

Whis 내가 기대하는 것입니다 포함 (5)

페이지 2의 기본 T-SQL은

입니다 나는 T-SQL은 SQL Express를 관리 Studio에 명령을 붙여 넣을 때 내가 설명한 결과를 얻을

사이가 사용하고

알 수 있습니다. 나는 페이지 2의 T-SQL을 사용하여 라인을 개정하는 경우

WHERE [t4].[ROW_NUMBER] BETWEEN 5 + 1 AND 5 + 5 

WHERE [t4].[ROW_NUMBER] BETWEEN 1 AND 5 

은 내가 PAGE1에 대한 기대했던 결과를 얻을 수 있습니다. 즉 처음 5 개 항목.
176 ADAMS Charles James 
620 ADAMS Charles James 
621 ADAMS Charles James 
660 ADAMS Charles James 
683 ADAMS Charles James 

그래서 한마디에 T-SQL 내가 원하는 결과를 얻을 수 TOP
사이 대신 사용하는 경우.

필자는 필터링 (where 절), 정렬 (orderBy) 및 페이징 (건너 뛰기 및 가져 오기)을 내 응용 프로그램 전체에서 사용하고 있으며 이것을 상당히 일반적으로 처리해야합니다.

  • LINQ는 TOP 대신 구문 BETWEEN을 사용하도록 강제 할 수있는 방법이 있나요?
  • 이 에 다르게 접근해야합니까?

긴 게시물에 대한 사과.

감사합니다, 사이먼 관계없이 SQL은 (그렇지 않으면 LINQ 또는) 생성 방법의

+0

두 번째 SQL 쿼리에 다른 Order By Clause가 있음을 유의하십시오. var orderedlist = query.OrderBy ("ArtistName asc")를 평가 해보십시오. ToList(); 먼저 그리고 그곳에서 페이지를 얻습니다. –

답변

0

, 당신 ORDER BY 중복 값이있는 열 경우, 당신은 다른 결과 쿼리를 실행할 때마다 얻을 수 있습니다.

ORDER BY [t3].[value] 때 많은 중복 값이 ​​포함 된 열을 정렬합니다.

Management Studio에서 매우 간단한 SQL SELECT를 실행하여이를 테스트 할 수 있습니다. 당신이 그것을 실행할 때마다, 당신은 다른 결과를 얻을 것이다.

일관된 결과를 얻는 한 가지 방법은 수행 한대로 ROW_NUMBER을 사용하는 것입니다. 또는 다른 열을 ORDER BY에 고유하게 추가하면 결과가 항상 같은 순서로 반환됩니다. 다른 열이 쿼리와 관련이 있는지 여부는 중요하지 않습니다. 단지 고유 한 것입니다.

+0

감사합니다. DOK, 일관된 결과를 얻으려면 "완료 한 것처럼 ROW_NUMBER"를 사용하는 것이 좋습니다. 사실 나는 ROW_NUMBER를 사용하지 않았고, SQL에 linq이 코드를 생성했기 때문에 그것을 제어 할 수있는 것으로 보이지 않습니다. 그건 정말 내 질문 - 내가 linq SQL에 "row_number"및 "첫 페이지 대신"단지 "대신"사용 "말할 수 있습니다. 결국 나는 내 모든 entites에 고유 한 열을 추가해야하고 제안한 바에 따라 order by 절의 마지막 부분에이를 고정해야합니다. 내가 이미 놀고 있었지만 좋은 해결책이 있는지 알고 싶다고 생각했습니다. 답장을 보내 주셔서 감사합니다. –

관련 문제