考虑IEnumerable扩展方法SingleOrDefault()和FirstOrDefault()。
msdn文件说明SingleOrDefault:
Returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.
鉴于来自msdn的FirstOrDefault(可能在使用OrderBy()或OrderByDescending()或根本不使用时)
Returns the first element of a sequence
考虑一些示例查询,并不总是清楚何时使用这两种方法:
1 2 3 4 5 6 7 8 9
| 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? |
问题
在决定在LINQ查询中使用SingleOrDefault()和FirstOrDefault()时,您遵循或建议什么约定?
如果结果集返回0条记录:
- SingleOrDefault返回类型的默认值(例如,int的默认值为0)
- FirstOrDefault返回类型的默认值
如果结果集返回1条记录:
- SingleOrDefault返回该记录
- FirstOrDefault返回该记录
如果结果集返回许多记录:
- SingleOrDefault抛出异常
- FirstOrDefault返回第一条记录
结论:
如果希望在结果集包含多个记录时引发异常,请使用SingleOrDefault。
如果不管结果集包含什么,您总是需要1条记录,请使用FirstOrDefault。
- 我想这是对的suggest罕见异常,其实也只是firstordefault大部分时间将是首选。我知道会有这样的案例,不是通常的海事组织。
- 第一FirstOrDefault返回新记录是记录均值(最后)/(一)旧的记录?你能澄清吗?
- DUK在线",它取决于你如何排序的记录。你可以使用orderby()或()之前调用firstordefault orderbydescending等。看到OP码的例子。
- 我喜欢这个答案太。有一些场合,特别是给出了在这里你真的想,你打算把thrown异常是罕见的,因为恰当的案例只是假装它到其他地方喷嘴对置并没有发生。当你想说"你是这异常强迫他人,也只是到手柄将制作更多的整个系统的鲁棒性。
- 这是一个非常明确的表示,所以可以很容易地理解。
whenever你使用SingleOrDefault,你明确的状态,query应该作为一个结果,在美元现在在单一的一个结果。在另一方面,当FirstOrDefault用,query可以返回任何量的结果,但你的状态,你只想要的第一人。 P / < >
我personally找到的semantics非常不同的和使用的一个适当的情况下,取决于上的expected结果,提高了readability。 P / < >
- 一个非常重要的区别是,如果对具有多个元素的序列使用singleOrDefault,它将引发异常。
- @卡米如果不破例的话,就和第一个或是最后一个一样。唯一的例外是它是单一或默认的。提出这一点很有意义,并把分歧的棺材钉在钉子上。
- 我必须说,从性能角度来看,first或default的工作速度比singleordefault快10倍,使用9000000个元素的list,class包含2个整数,func包含对这两个整数的搜索。在一个循环中搜索200次花了22秒在var v=list.singlerdefault(x=>x.id1==i&;x.id2==i)和var v=list.first或default(x=>x.id1==i&;x.id2==i)上;大约3秒
- @BitsandyTeshAndyMan如果SignleOrDefault在序列包含多个项时没有引发异常,则它的行为将与FirstOrDefault完全不同。FirstOrDefault返回第一个项,如果序列为空,则返回空值。singleOrDefault应返回唯一的项,如果序列为空或包含多个项,则返回空值,而不引发异常。
- @根据msdn文档,singleOrDefault"如果序列中有多个元素,则抛出异常"
- @是的,我知道。仔细阅读我的评论,我说的是singlerdefault应该做什么,而不是它应该做什么。当然,它应该做的是非常主观的。对我来说,"someThingorDefault"模式意味着:获取"something"的值。如果"something"不能返回值,则返回默认值。这意味着即使在"something"会引发异常的情况下,也应该返回默认值。所以,在single抛出异常的地方,在我看来,singleOrDefault应该返回默认值。
- @RSW继续我之前的评论:但是在序列中有多个项目的情况下,singleOrDefault的行为与single完全相同。他们都提出了一个例外。在我看来,这看起来有点奇怪,但我理解文档化行为背后的基本原理。也许,我从signleorDefault期望的行为应该在名为OnlyOrderFault的方法中实现,或者类似的方法中实现,在这种方法中,它应该返回序列的唯一项,或者在任何其他情况下(零个或多个项),它应该返回默认值。
- @谢谢你…我明白你在说什么了
- "我认为在大学bryanmenard wording SingleOrDefault是confusing如果你只是把它意味着什么的W/O型挖掘的API文档。它听起来像一只给我或给我任何,或"第一"(像SQL)。"你明确这一disagree状态的查询结果在最应该在单结果往往不甚。"我们可以预测,将有一个在搜索结果最符合单从"美国"的国家。默认是misleading和SQL经验,许多人已经知道,当你的"Don’t指定ORDER BY"沿W /顶1,你会得到一个由索引…………………
- 寻找在MSDN后,确认了这一singleordefault InvalidOperationException)当输入序列包含多个元素。
有 P / < >
之间的两个。 P / < >
semantical都: P / < >
- FirstOrDefaultreturns第一item of potentially多(或违约,如果没有exists)。
- SingleOrDefaultassumes,有单一的item和returns它(或违约,如果没有exists)。多个项目是在violation的合同,一个例外是thrown。
性能都 P / < >
-
FirstOrDefault也usually更快,它iterates直到它的finds元和腹部只到iterate整个enumerable当它没有被发现它。在许多案例,有高的概率找到一个item。 P / < >
-
SingleOrDefault需要去检查,如果有只有一元和therefore总是iterates整个enumerable。要精确,它iterates直到它finds的二元和throws一个例外。但在现在cases,没有第二元。 P / < >
结论 P / < >
在练习,你使用First/ FirstOrDefaultoften甚至在例当你为此承担的单一项目,到improve性能。你应该还记得,Single/ SingleOrDefault可以improve readability(因为它美国的assumption的单一item)和稳定性(因为它-它)和使用它appropriately。 P / < >
- +1"或者当您无法负担检查唯一性的费用时(例如在非常大的集合中)。"我在找这个。我还将在插入时添加强制唯一性,或者通过设计而不是在进行查询时添加强制唯一性!
- 我可以想象,当使用linq to对象时,SingleOrDefault会迭代很多对象,但如果linq正在与数据库对话,那么SingleOrDefault不需要迭代最多2个项目吗?只是想知道……
- @memetolsen考虑使用linq to sql-first或default的两个函数的代码spit使用top 1。singleOrDefault使用前2个。
- @我想我误解了"可枚举"这个词。我以为Stefan是指c Enumerable。
- @memetolsen在原始答案方面是正确的,您的评论是引用数据库的,所以我提供了从提供者那里发生的事情。虽然.NET代码只迭代2个以上的值,但数据库会访问所需的任意多个记录,直到达到第二个符合条件的记录为止。
- 问题是,您"通常"只期望一个(否则无论如何您都会得到一个异常)。所以"通常"它迭代所有…
- 关于singleOrDefault的性能考虑:它不必遍历整个集合。它只是查看返回的结果是否有多个元素。所以,我认为过程时间是可鄙的。
- @Aikan&ro:如果它不是一个列表或数组,它如何确定它是否有多个元素?假设它是.select或.where的返回值。一个"真正的"IEnumerable。
没有人提到在SQL中转换的first或default会做前1条记录,而singleordefault会做前2条记录,因为它需要知道是否有超过1条记录。
- 当我singleordefault冉通linqpad和VS,我永远不会有第二firstordefault I与选择,是选择能够取得第一,但只要我能告诉你不要选择2顶部。
- 我一直想在linqpad太让我害怕,因为和SQL查询,它完全从所有的行。我不知道这是怎么发生的?
- 这完全取决于对LINQ的供应商使用。例如,SQL和LINQ to SQL翻译到实体LINQ可以在不同的方式。我只是想linqpad与智商和FirstOrDefault()MySQL提供者,而不增加LIMIT 0,1SingleOrDefault()增加。
- 2.1对translates firstordefault EF芯顶(1),选择(2)选择singleordefault到顶部
对于LINQ->SQL:
单一违约
- 将生成类似"select*from users where userid=1"的查询
- 选择匹配的记录,如果找到多个记录,则引发异常
- 如果要根据主键/唯一键列提取数据,则使用
首次违约
- 将生成类似"从userid=1的用户中选择前1个*的查询"
- 选择第一个匹配行
- 如果要基于非主键/唯一键列提取数据,请使用
- 我认为您应该从single或default中删除"选择所有匹配行"
我用SingleOrDefault在situations在我的dictates逻辑,将无论是零或一个结果。如果有更多的,它是一个错误的情况,这是helpful。 P / < >
- 我发现,通常情况下,singleordefault集锦(一)不正确的滤波应用的在线的结果集,或与duplications那里是一个问题在下面的日期。更多的,往往不是,我发现自己比单用()和()singleordefault over the First()方法。
- 有对性能的影响单()和()singleordefault LINQ to Objects在线如果你有一个大的可枚举,但当谈起数据库(例如SQL Server)它将顶2的呼叫,如果你正确地说是设置呼叫指标是不昂贵的,我宁愿和快速失败可能的问题而不是找到的数据介绍其他数据通过以重复的问题时,调用了一firstordefault()或()。
singleordefault:你是说,"在现在"有一个item或"query或违约 firstordefault:你是说,"至少有一个item"或"query或违约 P / < >
说,联盟的下一个时间,你需要选择你要明智的选择成为可能。:) P / < >
- 具有可接受的结果,其实是在perfectly使用任何数= FirstOrDefault. More correctly: firstordefault `但我只在乎结果,在第一次的一个,也可能是没有结果的。有SingleOrDefault= 1或0的结果,如果有更多的是一个有误差的均值。至少有一个First)的结果,和我想它。有一Single= 1的结果是,更多的,是在一个不与我想要的。
在你的案例,我会用以下的: P / < >
选择id = = = 5:很好用singleordefault到这里,因为你没有想到一个[或] entity,如果你有超过一个entity id与5,有什么错误和例外绝对是值得的。 P / < >
当找人的第一个名字equals"鲍比",*能有超过一个(很可能)会认为),所以你应该neither也使用单一的第一选择,只是与你在操作上(如果"鲍比"returns太多的实体,用户到他的腹部refine搜索或选择一个乐队结果returned) P / < >
秩序由创作的日期应该也在performed与我在操作上的(unlikely到有只有一个实体,sorting不会停止使用之多;然而这implies)你想要的所有的实体sorted -如果你想要的只是一个单一的使用,firstordefault,会把每一个时间,如果你有超过一个实体。 P / < >
- 我disagree。如果你的数据库ID是主键的数据库已经执行,然后是唯一性的。浪费的CPU周期,如果是做CT检查,其工作的每一个数据库的查询是一个在线就傻了。
两者都是元素操作符,用于从序列中选择单个元素。但它们之间有一个微小的区别。如果满足以下条件,则singleOrDefault()运算符将引发异常:as firstOrDefault()不会对同一个元素引发任何异常。下面是例子。
1 2 3 4 5
| 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(); |
在你的最后一个例子: P / < >
1 2 3
| var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or doesn't matter? |
是的,它确实没有。如果你试着用SingleOrDefault()和query结果记录在比你会得到和例外。唯一的时间你可以安全的使用SingleOrDefault()还当你是唯一的期待和1只1的结果…… P / < >
因此,我现在了解到,如果您查询的数据保证是唯一的,即由数据库约束(如主键)强制执行,那么SingleOrDefault将是很好的。
或者有更好的方法来查询主键。
假设我的TableAcc
1 2 3 4 5
| AccountNumber - Primary Key, integer
AccountName
AccountOpenedDate
AccountIsActive
etc. |
我想查询一个AccountNumber 987654,我用
1
| var data = datacontext.TableAcc.FirstOrDefault(obj => obj.AccountNumber == 987654); |
回答中遗漏了一件事……
如果有多个结果,没有order by的first或default可以返回不同的结果,而服务器使用的索引策略正是基于这些结果。
就我个人而言,我无法忍受在代码中看到first或efault,因为对我来说,它表示开发人员不关心结果。尽管它可以作为强制执行最新/最早版本的一种方式,但它还是有帮助的。我不得不纠正许多由使用first或default的粗心开发人员引起的问题。
我不明白你为什么要使用FirstOrDefault(x=> x.ID == key),如果你使用Find(key),那么检索结果会更快。如果使用表的主键进行查询,则经验法则是始终使用Find(key)。FirstOrDefault应用于(x=> x.Username == username)等谓词。
由于问题的标题不特定于DB上的LINQ或要列出的LINQ/IEnumerable等,因此不应投反对票。
- 命名空间是一个Find()?
- 你能告诉我们好吗?仍然在等待一个答案。
- 可能是这样的:14032709 stackoverflow.com /问题/ / & hellip;
- "IEnumerable"这个词在问题体的第一行。如果你只看标题而不是实际的问题,结果贴出了一个错误的答案,那就是你的错误,也是一个完全合理的理由否决IMO。