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()
두 번째 항목이 있는지 확인하지 않으므로 약간 더 효율적입니다.
The only difference is that Single()
expects there to be only one item in the enumeration to begin with, and will throw an exception if there are more than one. You use .Single()
if you specifically want an exception thrown in this case.
If I recall, Single() checks if there is another element after the first one (and throws an exception if it's the case), while First() stops after getting it. Both throw an exception if the sequence is empty.
Personnally, I always use First().
Regarding peformance: A coworker and I were discussing the performance of Single vs First (or SingleOrDefault vs FirstOrDefault), and I was arguing for the point that First (or FirstOrDefault) would be faster and improve performance (I’m all about making our app run faster).
I’ve read several posts on Stack Overflow that debate this. Some say there are small performance gains using First instead of Single. This is because First would simply return the first item while Single must scan all the results to make sure there isn’t a duplicate (ie: if it found the item in the first row of the table, it still would scan every other row to make sure there isn’t a second value matching the condition which would then throw an error). I felt like I was on solid ground with “First” being faster than “Single” so I set out to prove it and put the debate to rest.
I setup a test in my database and added 1,000,000 rows of ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar(50) (filled with strings of numbers “0” to “999,9999”
I loaded the data and set ID as a primary key field.
Using LinqPad, my goal was to show that if you searched for a value on ‘Foreign’ or ‘Info’ using Single, that it would be much worse than using First.
I cannot explain the results I got. In almost every case, using Single or SingleOrDefault was slightly faster. This doesn’t make any logical sense to me, but I wanted to share that.
Ex: I used the following queries:
var q = TestTables.First(x=>x.Info == "314638") ;
//Vs.
Var q = TestTables.Single(x=>x.Info =="314638") ; //(this was slightly faster to my surprise)
I tried similar queries on the 'Foreign' key field which was not indexed thinking that would prove First is faster, but Single was always slightly faster in my tests.
They are different. Both of them assert that the result set is not empty, but single also asserts that there is not more than 1 result. I personally use Single in cases where I only expect there to be 1 result just because getting more than 1 result back is an error and probably should be treated as such.
You can try simple example to get difference. Exception will thrown on line 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);
A lot of people I know use FirstOrDefault(), but I tend to use SingleOrDefault() more because often it would be some sort of data inconsistency if there were more than one. This is dealing with LINQ-to-Objects, though.
Lets below are the records in Employee entity
Employeeid = 1: Only one employee with this ID
Firstname = Robert: More than one employee with this name
Employeeid = 10: No employee with this ID
Now understand what Single() and First() in detail
**Single()**
Single() is use to return single record which exists only one in a table, so below query will return Employee whose employee id =1 because we have Employee is one whose Employee id is 1. If we have two records for EmployeeId = 1 then it give the error, kindly see error below in second query where we are taking example of name.
Employee.Single(e => e.Employeeid == 1)
Above will return single record, which have 1 employeeId
Employee.Single(e => e.Firstname == "Robert")
Above will give exception because multilple records are in table for FirstName='Robert'
And exception will be
InvalidOperationException: Sequence contains more than one element
Employee.Single(e => e.Employeeid == 10)
Above again will throw exception because no record exists for id=10 and exception will be
InvalidOperationException: Sequence contains no elements.
For EmployeeId = 10 it will return null but we are using only Single() then it will give error to handle null error we should use SingleOrDefault().
**First()**
First() return from multiple same records according to order as we using ascending order on birthdate so it will return 'Rober' who is oldest.
Employee.OrderBy(e => e. Birthdate)
.First(e => e.Firstname == "Robert")
Above should return the oldest one robert as per DOB
Employee.OrderBy(e => e. Birthdate)
.First(e => e.Employeeid == 10)
Above will give the exception as no record for id =10
To avoid null exception we should use FirstOrDefault() not only First().
Note: We can use only First()/Single() when we damn sure that it must going to return not null value.
In both function **SingleOrDefault() OR FirstOrDefault()**
It will handled null exception, in case of no record found it will give null.
참고URL : https://stackoverflow.com/questions/2724096/linq-single-vs-first
'Programming' 카테고리의 다른 글
MySQL의 now () +1 일 (0) | 2020.05.07 |
---|---|
Angular는 AngularJS $ watch와 동일합니까? (0) | 2020.05.07 |
선택된 단일 선택 단추 레이블에 대한 CSS 선택기 (0) | 2020.05.07 |
Java를 사용하여 과학적 표기법없이 이중 값을 인쇄하려면 어떻게합니까? (0) | 2020.05.07 |
R에서 벡터를 청크로 나눕니다. (0) | 2020.05.07 |