[.net] LINQ Single과 First

LINQ :

쿼리가 단일 레코드를 반환한다는 것을 확신 할 때 Single()연산자 를 사용하는 것이 더 효율적 입니까?First()

차이가 있습니까?



답변

단일 레코드를 기대하는 경우 항상 코드에 명시하는 것이 좋습니다.

나는 다른 사람들이 왜 당신이 하나 또는 다른 것을 사용하는지 알고 있지만, 나는 당신 이 다른 것을 의미 할 때 왜 당신이 하나를 사용해서는 안되는지 설명 할 것이라고 생각했습니다 .

참고 : 내 코드에서, 나는 일반적으로 사용 FirstOrDefault()하고 SingleOrDefault()있지만 다른 질문입니다.

예를 들어, Customers복합 키 ( ID, Lang)를 사용하여 다른 언어로 저장하는 테이블을 보자 .

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();

위의이 코드는 가능한 논리 오류를 발생시킵니다 (추적하기 어려움). 여러 언어로 된 고객 레코드가 있다고 가정하면 둘 이상의 레코드를 반환하지만 항상 첫 번째 레코드 만 반환합니다. 예측할 수 없습니다.

귀하의 의도는 단일 Customer사용 을 반환하는 것이므로 Single();

다음은 예외를 던질 것입니다 (이 경우 원하는 것입니다).

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();

그런 다음 이마에 몸을 대고 자신에게 말하십시오. 나는 언어 분야를 잊었다! 다음은 올바른 버전입니다.

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();

First() 다음 시나리오에서 유용합니다.

DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();

하나의 객체를 반환하고 정렬을 사용하기 때문에 가장 최근에 반환 된 레코드가됩니다.

사용 Single()당신이 명시 적으로 항상 1 개 레코드를 반환해야 느낄 때 당신은 논리의 오류를 방지하는 데 도움이됩니다.


답변

조건과 일치하는 레코드가 두 개 이상 있으면 Single에서 예외가 발생합니다. 첫 번째는 항상 목록에서 첫 번째 레코드를 선택합니다. 쿼리가 1 개의 레코드 만 반환하면으로 갈 수 있습니다 First().

InvalidOperationException컬렉션이 비어 있으면 둘 다 예외 가 발생합니다. 또는을 사용할 수 있습니다 SingleOrDefault(). 목록이 비어 있으면 예외가 발생하지 않습니다.


답변

단일()

쿼리의 단일 특정 요소를 반환

사용시 : 정확히 1 개의 요소가 예상되는 경우; 0 이상 또는 1 이상

SingleOrDefault ()

쿼리의 단일 특정 요소를 반환하거나 결과를 찾지 못한 경우 기본값을 반환합니다

사용시 : 0 개 또는 1 개의 요소가 예상되는 경우. 목록에 2 개 이상의 항목이 있으면 예외가 발생합니다.

먼저()

여러 결과가 포함 된 쿼리의 첫 번째 요소를 반환합니다.

사용시 : 하나 이상의 요소가 예상되고 첫 번째 요소 만 원하는 경우 목록에 요소가 없으면 예외가 발생합니다.

FirstOrDefault ()

요소가 많은 목록의 첫 번째 요소를 반환하거나 목록이 비어있는 경우 기본값을 반환합니다.

사용시 : 여러 요소가 예상되고 첫 번째 요소 만 원하는 경우 또는 목록이 비어 있고 지정된 유형에 대한 기본값 (과 동일)을 원합니다 default(MyObjectType). 예를 들어 목록 유형이 목록 list<int>에서 첫 번째 숫자를 반환하고 목록이 비어 있으면 0을 반환합니다. 인 경우 list<string>목록에서 첫 번째 문자열을 반환하거나 목록이 비어 있으면 null을 반환합니다.


답변

이 두 방법 사이에는 미묘하고 의미적인 차이가 있습니다.

Single하나의 요소 만 포함해야하는 시퀀스에서 첫 번째 (및 유일한) 요소를 검색하는 데 사용 합니다. 시퀀스에 요소 이상이 Single있는 경우 하나의 요소 만 있어야한다고 표시했기 때문에 호출 하면 예외가 발생합니다.

First여러 요소를 포함 할 수있는 시퀀스에서 첫 번째 요소를 검색하는 데 사용 합니다. 시퀀스에 요소 이상이 있으면 시퀀스 First의 첫 번째 요소 만 필요하고 더 많은 요소가 있는지 신경 쓰지 않기 때문에 호출 하면 예외가 발생하지 않습니다.

시퀀스에 요소가없는 경우 두 메소드 모두 하나 이상의 요소가 존재할 것으로 예상하므로 두 메소드 호출 모두 예외가 발생합니다.


답변

하나 이상의 항목이있는 경우 예외가 발생하지 않게 하려면을 사용하십시오First() .

둘 다 효율적이며 첫 번째 항목을 가져갑니다. First()두 번째 항목이 있는지 확인하지 않으므로 약간 더 효율적입니다.

유일한 차이점은 Single()열거에 항목이 하나만있을 것으로 예상하고 둘 이상인 경우 예외가 발생한다는 것입니다. 당신은 사용 .Single() 특별히 던져 예외하려는 경우 이 경우입니다.


답변

내가 기억하면 Single ()은 첫 번째 요소 다음에 다른 요소가 있는지 확인하고 (있는 경우 예외가 발생) First ()는 요소를 가져온 후 중지합니다. 시퀀스가 비어 있으면 예외가 발생합니다.

개인적으로, 나는 항상 First ()를 사용합니다.


답변

성능과 관련하여 : 동료와 나는 Single vs First (또는 SingleOrDefault vs FirstOrDefault)의 성능에 대해 논의하고 있었고 First (또는 FirstOrDefault)가 더 빨라지고 성능이 향상 될 것이라고 주장했습니다. 더 빨리 달려).

나는 이것을 토론하는 스택 오버플로에 대한 여러 게시물을 읽었습니다. 일부는 Single 대신 First를 사용하면 약간의 성능 향상이 있다고 말합니다. 이는 First가 단순히 첫 번째 항목을 반환하는 반면 Single은 모든 결과를 스캔하여 중복이 없는지 확인해야하기 때문입니다 (예 : 테이블의 첫 번째 행에서 항목을 찾은 경우 여전히 다른 행을 조건과 일치하는 두 번째 값이 없는지 확인하십시오. 그러면 오류가 발생합니다). 나는“싱글”보다“첫 번째”가 더 빠르면서 확고한 입장에있는 것 같아서 그것을 증명하고 토론을 쉬게했다.

데이터베이스에 테스트를 설정하고 1,000,000 행의 ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar (50) 행을 추가했습니다 (숫자 “0”- “999,9999”로 채워짐)

데이터를로드하고 ID를 기본 키 필드로 설정했습니다.

LinqPad를 사용하여 내 목표는 Single을 사용하여 ‘Foreign’또는 ‘Info’에서 값을 검색하면 First를 사용하는 것보다 훨씬 나쁘다는 것을 보여주었습니다.

내가 얻은 결과를 설명 할 수 없습니다. 거의 모든 경우에 Single 또는 SingleOrDefault를 사용하는 것이 약간 더 빠릅니다. 이것은 나에게 논리적으로 이해가되지 않지만 공유하고 싶었습니다.

예 : 다음 쿼리를 사용했습니다.

var q = TestTables.First(x=>x.Info == "314638") ;
//Vs.
Var q = TestTables.Single(x=>x.Info =="314638") ; //(this was slightly faster to my surprise)

나는 ‘Foreign’키 필드에 대해 비슷한 쿼리를 시도했지만 First는 더 빠르다고 생각하는 인덱스되지는 않았지만 Single은 항상 테스트에서 약간 빠릅니다.