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.
11 回答
如果您期望单条记录,那么在代码中明确表示总是好的 .
我知道其他人已经写过为什么你使用其中一个,但我想我会说明为什么你不应该使用一个,当你另一个 .
注意:在我的代码中,我通常会使用
FirstOrDefault()
和SingleOrDefault()
,但这是一个不同的问题 .例如,使用复合键(
ID
,Lang
)以不同语言存储Customers
的表:上面的代码引入了可能的逻辑错误(难以跟踪) . 它将返回多个记录(假设您有多种语言的客户记录),但它总是只返回第一个...有时可能有效......但不能返回其他语言 . 这是不可预测的 .
既然你的意图是返回单
Customer
使用Single()
;以下将抛出一个异常(在这种情况下你想要的):
然后,你只需按下额头,然后对自己说......哎呀!我忘记了语言领域!以下是正确的版本:
First()
在以下场景中很有用:它将返回一个对象,并且由于您正在使用排序,它将是返回的最新记录 .
当你觉得它应该显式地总是返回1条记录时使用
Single()
将帮助你避免逻辑错误 .如果找到符合条件的多条记录,则Single将抛出异常 . 首先将始终从列表中选择第一条记录 . 如果查询只返回1条记录,则可以使用
First()
.如果集合为空,则两者都将抛出
InvalidOperationException
异常 . 或者,您可以使用SingleOrDefault()
. 如果列表为空,则不会抛出异常Single()
SingleOrDefault()
First()
FirstOrDefault()
这两种方法之间存在细微的语义差异 .
使用
Single
从应该包含一个元素但不再包含一个元素的序列中检索第一个(也是唯一的)元素 . 如果序列具有多于on元素,则调用Single
将导致抛出异常,因为您指示应该只有一个元素 .使用
First
从可包含任意数量元素的序列中检索第一个元素 . 如果序列具有多于on元素,则调用First
将不会导致抛出异常,因为您指示您只需要序列中的第一个元素而不关心是否存在更多元素 .如果序列不包含任何元素,则两个方法调用都将导致抛出异常,因为两个方法都期望至少存在一个元素 .
如果我记得,Single()检查第一个元素后面是否有另一个元素(如果是这种情况则抛出异常),而First()在获取后停止 . 如果序列为空,则两者都抛出异常 .
个人而言,我总是使用First() .
如果您没有特别想要在有多个项目的情况下抛出异常, use First() .
两者都很有效率,拿第一项 .
First()
稍微提高效率,因为它不会检查是否有效还有第二项 .唯一的区别是
Single()
期望枚举中只有一个项目开始,并且如果有多个项目将抛出异常 . 如果您特别希望在这种情况下抛出异常,则使用.Single()
.关于性能:一位同事和我正在讨论Single vs First(或SingleOrDefault vs FirstOrDefault)的性能,我正在争论First(或FirstOrDefault)会更快并提高性能(我只是为了制作我们的应用程序)跑得更快) .
我已经阅读了有关Stack Overflow的几篇文章 . 有人说使用First而不是Single会有很小的性能提升 . 这是因为First只返回第一项,而Single必须扫描所有结果以确保没有重复(即:如果它在表的第一行中找到该项,它仍然会扫描每隔一行确保没有第二个值匹配条件然后会抛出错误) . 我觉得自己处于坚实的基础上,“第一”比“单身”更快,所以我开始证明这一点并让辩论得以休息 .
我在我的数据库中设置了一个测试并添加了1,000,000行ID UniqueIdentifier外部UniqueIdentifier信息nvarchar(50)(填充了数字“0”到“999,9999”的字符串
我加载了数据并将ID设置为主键字段 .
使用LinqPad,我的目标是表明如果你使用Single搜索'Foreign'或'Info'的值,那将比使用First更糟糕 .
我无法解释我得到的结果 . 几乎在所有情况下,使用Single或SingleOrDefault稍微快一些 . 这对我来说没有任何合理意义,但我想分享一下 .
例如:我使用了以下查询:
我在'外部'关键字段上尝试了类似的查询,这个字段没有被编入索引,认为First会更快,但Single在我的测试中总是稍微快一些 .
它们是不同的 . 它们都断言结果集不为空,但是单个也断言结果不超过1 . 我个人使用Single,我只希望得到1个结果,因为得到多于1个结果是一个错误,可能应该这样对待 .
您可以尝试简单的示例来获得差异 . 第3行会抛出异常;
我认识的很多人都使用FirstOrDefault(),但我更倾向于使用SingleOrDefault(),因为如果有多个数据不一致,通常会出现某种数据不一致 . 不过,这是在处理LINQ-to-Objects .