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


当前回答

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

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

其他回答

如果结果集返回0条记录:

SingleOrDefault返回类型的默认值(例如int的默认值为0) FirstOrDefault返回类型的默认值

如果结果集返回1条记录:

SingleOrDefault返回该记录 FirstOrDefault返回该记录

如果你的结果集返回很多记录:

SingleOrDefault抛出异常 FirstOrDefault返回第一条记录

结论:

如果希望在结果集包含许多记录时抛出异常,请使用SingleOrDefault。

如果无论结果集包含什么,您总是想要1条记录,请使用FirstOrDefault

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

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

在你的情况下,我会使用以下方法:

select by ID==5:在这里使用SingleOrDefault是可以的,因为你希望有一个[或没有]实体,如果你有多个ID为5的实体,那就有问题了,肯定值得异常处理。

当搜索名字等于“Bobby”的人时,可能会有不止一个(我认为很有可能),所以你既不应该使用Single也不应该使用first,只需使用where操作选择(如果“Bobby”返回太多实体,用户必须优化他的搜索或选择返回的结果之一)

按创建日期的顺序也应该执行一个where操作(不太可能只有一个实体,排序不会有太大的用处;)这意味着你想要所有的实体排序-如果你想要一个,使用FirstOrDefault, Single会抛出每次如果你有多个实体。

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

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

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

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