programing

LINQ 단일 대 첫 번째

projobs 2023. 6. 3. 11:34
반응형

LINQ 단일 대 첫 번째

LINQ:

사용하는 것이 더 효율적입니까?Single() over 위교 환원의.First()쿼리가 단일 레코드를 반환한다는 것을 확실히 알 때마다?

차이가 있나요?

단일 레코드가 필요한 경우 코드에 명시적으로 표시하는 것이 좋습니다.

다른 사람들이 당신이 이것저것을 사용하는 이유를 썼다는 것을 알지만, 저는 당신이 다른 것을 의미할 때, 왜 당신이 그것을 사용하지 말아야 하는지 설명하려고 생각했습니다.

참고: 내 코드에서는 일반적으로 다음을 사용합니다.FirstOrDefault()그리고.SingleOrDefault()하지만 그것은 다른 질문입니다.

예를 들어, 저장하는 표를 예로 들어 보겠습니다.Customers 키( 복합키다사표언다시니됩어로른여용하를▁in다▁languages▁using▁(니▁a표▁key▁different시됩)를 사용하여 다른 언어로.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개를 반환해야 한다고 느낄 때 논리 오류를 방지하는 데 도움이 됩니다.

싱글은 기준과 일치하는 레코드를 둘 이상 발견하면 예외를 던집니다.First는 항상 목록에서 첫 번째 레코드를 선택합니다.쿼리가 레코드를 하나만 반환하는 경우 다음 작업을 수행할 수 있습니다.First().

둘 다 던질 것입니다.InvalidOperationException컬렉션이 비어 있는 경우 예외입니다. 또사할수있다니습용을 할 수 있습니다.SingleOrDefault()

싱글()

쿼리의 특정 단일 요소를 반환합니다.

사용 시: 정확히 1개의 요소가 예상되는 경우, 0 또는 1보다 크지 않습니다.목록이 비어 있거나 둘 이상의 요소가 있는 경우 "시퀀스에 둘 이상의 요소가 포함됨" 예외가 발생합니다.

단일 또는 기본값()

쿼리의 특정 단일 요소를 반환하거나 결과를 찾을 수 없는 경우 기본값을 반환합니다.

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

첫 번째()

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

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

첫 번째 또는 기본값()

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

사용 시: 여러 개의 요소가 필요하고 첫 번째 요소만 원하는 경우.또는 목록이 비어 있고 지정된 유형의 기본값을 다음과 같이 지정합니다.default(MyObjectType)를 들어, 목록 이 ": " " 목록유다같경은우과음"인 list<int>목록의 첫 번째 숫자를 반환하거나 목록이 비어 있으면 0을 반환합니다. 그것이 면다그라면.list<string>목록에서 첫 번째 문자열을 반환하거나 목록이 비어 있으면 null을 반환합니다.

두 개 이상의 항목이 있는 경우 예외를 발생시키지 않으려면 을 사용합니다.

둘 다 효율적입니다, 첫 번째 항목을 가져가세요. First()두 번째 항목이 있는지 확인하는 것이 번거롭지 않기 때문에 약간 더 효율적입니다.

유일한 차이점은Single()열거형에 시작할 항목이 하나만 있어야 하며, 둘 이상일 경우 예외를 던집니다.사용자 .Single() 경우에는 예외를 적용할 수 있습니다.

이 두 방법 사이에는 미묘한 의미론적 차이가 있습니다.

사용하다Single하나 이상의 요소를 포함하지 않아야 하는 시퀀스에서 첫 번째(그리고 유일한) 요소를 검색합니다.시퀀스에 두 개 이상의 요소가 있는 경우 호출:Single요소가 하나만 있어야 한다고 지정했기 때문에 예외가 발생합니다.

사용하다First임의의 수의 요소를 포함할 수 있는 시퀀스에서 첫 번째 요소를 검색합니다.시퀀스에 두 개 이상의 요소가 있는 경우 호출:First시퀀스에 첫 번째 요소만 필요하고 더 많은 요소가 있는지 여부는 상관없다고 표시했기 때문에 예외가 발생하지 않습니다.

시퀀스에 요소가 없는 경우 두 메서드 호출 모두 하나 이상의 요소가 있어야 하므로 예외가 발생합니다.

첫 번째()는 받은 후에 중지되는 반면, 첫 번째()는 첫 번째() 이후에 다른 요소가 있는지 확인합니다(경우에 따라 예외를 던집니다).시퀀스가 비어 있으면 둘 다 예외를 던집니다.

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

성능 관련:한 동료와 Single vs. First(또는 SingleOrDefault vs. FirstOrDefault)의 성능에 대해 논의하고 있었는데, 저는 First(또는 FirstOrDefault)가 더 빠르고 성능을 향상시킬 것이라고 주장했습니다(앱을 더 빨리 실행하는 것이 중요합니다).

저는 스택 오버플로에서 이것을 논쟁하는 게시물을 여러 번 읽었습니다.어떤 사람들은 싱글 대신 퍼스트를 사용하면 성능이 약간 향상된다고 말합니다.이는 First가 첫 번째 항목을 반환하는 반면 Single은 모든 결과를 스캔하여 중복 항목이 없는지 확인해야 하기 때문입니다(즉, 테이블의 첫 번째 행에서 항목을 발견한 경우에도 조건과 일치하는 두 번째 값이 없는지 확인하기 위해 다른 모든 행을 스캔하여 오류를 발생시킵니다).저는 "첫 번째"가 "싱글"보다 더 빠른 것에 대해 확고한 입장에 있는 것처럼 느껴져서 그것을 증명하고 토론을 잠재우기 위해 착수했습니다.

데이터베이스에 테스트를 설정하고 ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar(50) 1,000,000 행을 추가했습니다("0"부터 "999,999"까지의 숫자 문자열로 채워짐).

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

LinqPad를 사용하여 싱글을 사용하여 '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)

First가 더 빠르다는 것을 증명할 수 있을 것이라고 생각하여 색인화되지 않은 'Foreign' 키 필드에서 유사한 쿼리를 시도했지만, 테스트에서 Single은 항상 약간 더 빨랐습니다.

그들은 다릅니다.둘 다 결과 집합이 비어 있지 않다고 주장하지만 단일은 결과가 1개를 넘지 않는다고 주장합니다.저는 개인적으로 1개 이상의 결과를 얻는 것이 오류이고 아마도 그렇게 취급되어야 한다고 해서 1개의 결과만 있을 것으로 예상하는 경우에 싱글을 사용합니다.

여러분은 차이를 얻기 위해 간단한 예를 시도할 수 있습니다.예외는 3행에 던져집니다;

        List<int> records = new List<int>{1,1,3,4,5,6};
        var record = records.First(x => x == 1);
        record = records.Single(x => x == 1);

제가 아는 많은 사람들이 FirstOrDefault()를 사용하지만 둘 이상의 데이터가 있을 경우 데이터 불일치가 발생할 수 있기 때문에 SingleOrDefault()를 더 많이 사용하는 경향이 있습니다.하지만 이 작업은 LINQ-to-Objects를 처리합니다.

직원 엔티티의 레코드:

Employeeid = 1이 ID를 가진 직원 한 명만

Firstname = Robert이 이이을가진직둘원이상직원인 직원이 둘 이상 .

Employeeid = 10.

이제 무엇을 이해할 필요가 있습니다.Single()그리고.First()세밀하게 말하면

싱글()

하는 데 는 " " " " " ( ) 은 " 고 " " 를 합니다.employeed =1는 오직 한 의 직원만 입니다.Employeed1. 만약 우리가 2개의 기록을 가지고 있다면.EmployeeId = 1 두 하십시오). 여기서 예제를 사용하고 있습니다.Firstname.

Employee.Single(e => e.Employeeid == 1)

의 내용은 의 레코드를 1개의 는 1개의 레코드로 합니다.employeeId

Employee.Single(e => e.Firstname == "Robert")

테이블에 여러 레코드가 있으므로 위의 경우 예외가 발생합니다.FirstName='Robert'는 외는다과같다예니입니다.

잘못된 작업예외:시퀀스에 두 개 이상의 요소가 포함되어 있습니다.

Employee.Single(e => e.Employeeid == 10)

이 경우에도 id=10에 대한 레코드가 없기 때문에 예외가 발생합니다.예외는 다음과 같습니다.

잘못된 작업예외:시퀀스에 요소가 없습니다.

위해서EmployeeId = 10하지만 null을 때문에 null을 합니다.Single()그것은 오류를 던질 것입니다.하기 위해서는 null 오를처면다사합니용다야해음을을 .SingleOrDefault().

첫 번째()

First는 First()에 따라 합니다.birthdate그래서 그것은 가장 나이가 많은 '로버트'를 돌려줄 것입니다.

Employee.OrderBy(e => e. Birthdate)
.First(e => e.Firstname == "Robert")

위는 DOB에 따라 가장 오래된 로버트를 반환해야 합니다.

Employee.OrderBy(e => e. Birthdate)
.First(e => e.Employeeid == 10)

ID = 10에 대한 레코드가 없으므로 위에서 예외를 발생시킵니다. null 예를방사합니야다용을 사용해야 .FirstOrDefault()First().

참고: 다음만 사용할 수 있습니다.First()/Single()값을 할 수 절대적으로 때.

두 함수 모두 SingleOrDefault() 또는 FirstOrDefault()사용하여 null 예외를 처리합니다. 레코드를 찾을 수 없는 경우 null을 반환합니다.

언급URL : https://stackoverflow.com/questions/2724096/linq-single-vs-first

반응형