LINQ: SingleOrDefault를 사용할 때와필터링 기준이 있는 FirstOrDefault()
방법 IEnumberable 확장 방법을 .SingleOrDefault()
그리고.FirstOrDefault()
다음과 같은 MSDN 문서:
시퀀스의 유일한 요소를 반환하거나 시퀀스가 비어 있는 경우 기본값을 반환합니다. 이 메서드는 시퀀스에 두 개 이상의 요소가 있는 경우 예외를 발생시킵니다.
반면에 MSDN에서 (아마도 사용할 때).OrderBy()
또는OrderByDescending()
전혀), 예를 들어,
시퀀스의 첫 번째 요소를 반환합니다.
몇 가지 예제 쿼리를 생각해 보십시오. 이 두 가지 방법을 언제 사용해야 할지 항상 명확한 것은 아닙니다.
var someCust = db.Customers
.SingleOrDefault(c=>c.ID == 5); //unlikely(?) to be more than one, but technically COULD BE
var bobbyCust = db.Customers
.FirstOrDefault(c=>c.FirstName == "Bobby"); //clearly could be one or many, so use First?
var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or does it matter?
질문.
사용하기로 결정할 때 어떤 규칙을 따르거나 제안합니까?SingleOrDefault()
그리고.FirstOrDefault()
LINQ 쿼리에서?
결과 집합이 0개의 레코드를 반환하는 경우:
SingleOrDefault
0)에 대한 합니다. 예: int 기본값 0FirstOrDefault
" " " " 에 합니다.
결과 세트가 1개의 레코드를 반환하는 경우:
SingleOrDefault
합니다.FirstOrDefault
합니다.
결과 집합이 많은 레코드를 반환하는 경우:
SingleOrDefault
를 던집니다.FirstOrDefault
번째 첫번레코를반환합니다드째▁the첫다를 반환합니다.
결론:
레코드가 시키려면 결과집합많레은코포경함예발우다사다음용니합을면려생키시외를 사용합니다.SingleOrDefault
.
결과 세트에 포함된 레코드가 무엇이든 상관없이 항상 하나의 레코드를 원한다면 다음을 사용합니다.FirstOrDefault
를 사용할 때마다 쿼리가 최대 단일 결과를 생성해야 한다는 점을 명확히 설명합니다.반면에 를 사용하는 경우 쿼리는 모든 양의 결과를 반환할 수 있지만 사용자는 첫 번째 결과만 원한다고 말합니다.
저는 개인적으로 의미론이 매우 다르다는 것을 알고 있으며 예상 결과에 따라 적절한 의미론을 사용하면 가독성이 향상됩니다.
있어
- 의미론적 차이
- 경기력의 차이
양자간에
의미론적 차이:
FirstOrDefault
다중(또는 기본값이 없는 경우)일 가능성이 있는 첫 번째 항목을 반환합니다.SingleOrDefault
단일 항목이 있다고 가정하고 이 항목을 반환합니다(또는 항목이 없는 경우 기본값).여러 항목이 계약 위반이므로 예외가 발생합니다.
성능 차이
FirstOrDefault
일반적으로 더 빠르며, 요소를 찾을 때까지 반복하고 찾지 못할 때만 전체 열거형을 반복하면 됩니다.많은 경우, 아이템을 찾을 확률이 높습니다.SingleOrDefault
요소가 하나만 있는지 확인해야 하므로 항상 전체 열거형을 반복합니다.정확하게는 두 번째 요소를 찾아 예외를 던질 때까지 반복합니다.하지만 대부분의 경우 두 번째 요소는 없습니다.
결론
사용하다
FirstOrDefault
항목이 몇 개 있는지 또는 고유성을 확인할 여유가 없는 경우(예: 매우 큰 컬렉션).컬렉션에 항목을 추가할 때 고유성을 확인하면 해당 항목을 검색할 때 다시 확인하는 데 비용이 너무 많이 들 수 있습니다.사용하다
SingleOrDefault
성능에 너무 신경 쓰지 않고 단일 항목에 대한 가정이 독자에게 명확한지 확인하고 런타임에 확인하려는 경우.
실제로는 다음과 같이 사용합니다.First
/FirstOrDefault
종종 단일 항목을 가정하는 경우에도 성능을 향상시키기 위해 사용됩니다.당신은 여전히 기억해야 합니다.Single
/SingleOrDefault
가독성(단일 항목의 가정을 명시하기 때문에)과 안정성(확인하기 때문에)을 개선하고 적절하게 사용할 수 있습니다.
SQL에서 변환된 FirstOrDefault가 TOP 1 레코드를 수행하고 SingleOrDefault가 TOP 2 레코드를 수행한다는 사실은 아무도 언급하지 않았습니다. 레코드가 두 개 이상 있는지 알아야 하기 때문입니다.
LINQ -> SQL의 경우:
단일 또는 기본값
- "userid가 = 1인 사용자로부터 TOP 2 * 선택"과 같은 쿼리를 생성합니다.
- 일치하는 레코드 선택, 둘 이상의 레코드가 발견되면 예외를 던집니다.
- 기본/고유 키 열을 기반으로 데이터를 가져오는 경우 사용
첫 번째 또는 기본값
- "userid가 = 1인 사용자에서 상위 1 * 선택"과 같은 쿼리를 생성합니다.
- 일치하는 첫 번째 행 선택
- 기본/고유 키 열이 아닌 키 열을 기준으로 데이터를 가져오는 경우 사용
사용합니다SingleOrDefault
내 논리가 0이거나 하나의 결과가 될 것이라고 지시하는 상황에서.더 있으면 오류 상황이라 도움이 됩니다.
이 경우 다음을 사용합니다.
ID==5로 선택: 여기서 SingleOrDefault를 사용해도 괜찮습니다. 하나의 엔티티가 필요하거나 하나의 엔티티가 없어야 하기 때문입니다. ID가 5인 엔티티가 두 개 이상 있는 경우에는 잘못된 것이 있으며 분명히 예외가 있을 수 있습니다.
이름이 "Bobby"와 동일한 사람을 검색할 때, 둘 이상일 수 있습니다(아마도 제 생각에는). 싱글이나 퍼스트를 사용하지 말고, 위치 연산으로 선택하십시오("Bobby"가 너무 많은 엔티티를 반환하는 경우, 사용자는 검색을 세분화하거나 반환된 결과 중 하나를 선택해야 합니다).
생성 날짜별 순서도 Where-operation을 사용하여 수행해야 합니다(엔티티가 하나만 있을 가능성은 낮지만 정렬은 그다지 유용하지 않습니다). 그러나 이것은 모든 엔터티를 정렬하기를 원한다는 것을 의미합니다. 단 하나만 원한다면 FirstOrDefault를 사용하고, 둘 이상의 엔터티가 있을 때마다 Single이 던집니다.
단일 또는 기본값:쿼리 또는 기본 FirstOrDefault와 일치하는 항목이 "최대" 하나 있다고 말씀하시는 것입니다.쿼리 또는 기본값과 일치하는 "최소한"개의 항목이 있다는 것입니다.
다음 번에 선택해야 할 때 큰 소리로 말하면 현명하게 선택할 수 있을 것입니다.:)
둘 다 요소 연산자이며 시퀀스에서 단일 요소를 선택하는 데 사용됩니다.하지만 그들 사이에는 약간의 차이가 있습니다.SingleOrDefault() 연산자는 둘 이상의 요소가 조건을 충족하는 경우 예외를 던집니다. 반면 FirstOrDefault()는 동일한 요소에 대해 예외를 던지지 않습니다.여기 그 예가 있습니다.
List<int> items = new List<int>() {9,10,9};
//Returns the first element of a sequence after satisfied the condition more than one elements
int result1 = items.Where(item => item == 9).FirstOrDefault();
//Throw the exception after satisfied the condition more than one elements
int result3 = items.Where(item => item == 9).SingleOrDefault();
마지막 예에서는 다음과 같습니다.
var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or doesn't matter?
네, 포함되었습니다. 당신이 하려고 합니다.SingleOrDefault()
그리고 쿼리는 당신이 얻을 수 있는 기록 이상의 결과와 예외를 초래합니다.할 수 있는 은 안하게사수있유시입니다.SingleOrDefault()
오직 하나의 결과만을 기대할 때...
그래서 제가 지금 이해하는 바로는SingleOrDefault
기본 키와 같은 DB 제약 조건에 의해 수행되는 고유한 데이터를 쿼리하는 경우 유용합니다.
아니면 기본 키를 쿼리하는 더 나은 방법이 있습니까?
내 TableAcc가 있다고 가정할 때
AccountNumber - Primary Key, integer
AccountName
AccountOpenedDate
AccountIsActive
etc.
그리고 나는 문의하고 싶습니다.AccountNumber 987654
사용합니다
var data = datacontext.TableAcc.FirstOrDefault(obj => obj.AccountNumber == 987654);
생각에는 내생에는각는▁in에생각FirstOrDefault
너무 많이 사용되고 있습니다.대부분의 경우 데이터를 필터링할 때 논리적 조건과 일치하는 요소 모음을 가져오거나 고유한 단일 요소(예: 사용자, 책, 게시물 등)를 사용하여 고유한 요소를 반환해야 합니다.그렇기 때문에 우리는 심지어 그렇게 말할 수 있습니다.FirstOrDefault()
코드 냄새는 뭔가 문제가 있어서가 아니라 너무 자주 사용되고 있기 때문입니다.이 블로그 게시물은 주제를 자세히 살펴봅니다.IMO 대부분의 경우SingleOrDefault()
훨씬 더 나은 대안이므로 이 실수를 조심하고 계약과 기대를 명확하게 나타내는 가장 적절한 방법을 사용해야 합니다.
답변에서 한 가지 누락된 점이 있습니다.
결과가 여러 개인 경우, 순서가 없는 FirstOrDefault는 서버에서 사용한 인덱스 전략에 따라 다른 결과를 가져올 수 있습니다.
개인적으로 코드에서 FirstOrDefault를 보는 것은 참을 수 없습니다. 왜냐하면 개발자가 결과에 관심이 없다고 말하기 때문입니다.최신/초기 적용 방법으로 유용할 수 있지만 주문과 함께.저는 FirstOrDefault를 사용하는 부주의한 개발자들로 인해 발생한 많은 문제들을 수정해야 했습니다.
기본적으로 이 기능은 데이터를 정리하기 위한 일종의 검증 기능을 제공합니다. 하나를 선택하면 둘 다 데이터를 제공하지만 SingleOrDefault는 예상되는 데이터의 결과가 1개만 있어야 하고 더 많은 1개를 뱉으면 저장 프로시저 또는 쿼리가 이러한 결과를 초래한 이유를 확인해야 합니다.어쨌든 중복된 항목은 쿼리에서 절대 좋지 않습니다.
나는 GitHub에서 다양한 방법의 사용에 대해 구글에 문의했습니다.이 작업은 각 방법에 대해 Google 검색 쿼리를 실행하고 "site:github.com file:cs..." 쿼리를 사용하여 github.com 도메인 및 .cs 파일 확장명으로 쿼리를 제한하는 방식으로 수행됩니다."
Single* 방법보다 First* 방법이 더 일반적으로 사용되는 것 같습니다.
| Method | Results |
|----------------------|---------|
| FirstAsync | 315 |
| SingleAsync | 166 |
| FirstOrDefaultAsync | 357 |
| SingleOrDefaultAsync | 237 |
| FirstOrDefault | 17400 |
| SingleOrDefault | 2950 |
나는 당신이 왜 그것을 사용하는지 이해할 수 없습니다.FirstOrDefault(x=> x.ID == key)
가 훨씬 될 수 .Find(key)
테블의기키쿼본경리는항사다다용니합음우상을 사용하는 입니다.Find(key)
.FirstOrDefault
다음과 같은 술어에 사용되어야 합니다.(x=> x.Username == username)
질문의 제목이 DB의 linq 또는 linq to list/IEnumberable 등에 특정되지 않았기 때문에 이것은 다운 투표를 받을 자격이 없습니다.
언급URL : https://stackoverflow.com/questions/1745691/linq-when-to-use-singleordefault-vs-firstordefault-with-filtering-criteria
'programing' 카테고리의 다른 글
WPF textBox에 새 줄을 추가하지 않음을 입력합니다. (0) | 2023.05.05 |
---|---|
크기 조정 후 확장기의 내용에 맞게 WPF 창의 크기를 유지하는 방법 (0) | 2023.05.05 |
장고 세션 (0) | 2023.05.05 |
연결 문자열에서 Trusted_Connection과 Integrated Security의 차이점은 무엇입니까? (0) | 2023.05.05 |
파이썬을 사용하여 mongodb에서 커서의 길이를 얻는 방법은 무엇입니까? (0) | 2023.05.05 |