考虑IEnumerable扩展方法SingleOrDefault()和FirstOrDefault()

MSDN文档SingleOrDefault:

返回序列中唯一的元素,如果序列为空则返回默认值;如果序列中有多个元素,此方法将引发异常。

而来自MSDN的FirstOrDefault(假设在使用OrderBy()或orderbydescent()或根本不使用时),

返回序列的第一个元素

考虑一些示例查询,并不总是清楚何时使用这两个方法:

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()时,你遵循或建议什么约定?


当前回答

SingleOrDefault:您的意思是“最多”有一个项与查询或默认值匹配 FirstOrDefault:您的意思是有“至少”一项与查询或默认值匹配

下次你需要选择的时候大声说出来,你可能会做出明智的选择。:)

其他回答

我不明白为什么你要使用FirstOrDefault(x=> x.ID == key),当你使用Find(key)可以更快地检索结果时。如果使用表的Primary键进行查询,经验法则是始终使用Find(key)。FirstOrDefault应该用于谓词,如(x=> x. username == username)等。

这个问题的标题并不专门针对DB上的linq或linq到List/IEnumerable等,所以不应该被否决。

我查询了谷歌在GitHub上不同方法的使用情况。这是通过对每个方法运行谷歌搜索查询,并通过使用查询“site:github.com file:cs…”来限制查询到github.com域和.cs文件扩展名。

似乎第一个*方法比单一*方法更常用。

| Method               | Results |
|----------------------|---------|
| FirstAsync           |     315 |
| SingleAsync          |     166 |
| FirstOrDefaultAsync  |     357 |
| SingleOrDefaultAsync |     237 |
| FirstOrDefault       |   17400 |
| SingleOrDefault      |    2950 |

所以,正如我现在所理解的,SingleOrDefault将是很好的,如果你正在查询数据,保证是唯一的,即强制的DB约束,如主键。

或者是否有更好的方法来查询主键。

假设我的TableAcc有

AccountNumber - Primary Key, integer
AccountName
AccountOpenedDate
AccountIsActive
etc.

和我想查询一个AccountNumber 987654,我使用

var data = datacontext.TableAcc.FirstOrDefault(obj => obj.AccountNumber == 987654);

在回答中漏掉了一件事....

如果有多个结果,没有排序by的FirstOrDefault可以根据服务器碰巧使用的索引策略返回不同的结果。

就我个人而言,我无法忍受在代码中看到FirstOrDefault,因为对我来说,这表明开发人员不关心结果。通过命令,它可以作为一种强制执行最新/最早的方式。我不得不纠正许多由于粗心的开发人员使用FirstOrDefault而引起的问题。

没有人提到SQL中转换的FirstOrDefault执行TOP 1记录,而SingleOrDefault执行TOP 2记录,因为它需要知道是否有多个记录。