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


当前回答

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

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

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

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

其他回答

In my opinion FirstOrDefault is being overused a lot. In the majority of the cases when you’re filtering data you would either expect to get back a collection of elements matching the logical condition or a single unique element by its unique identifier – such as a user, book, post etc... That’s why we can even get as far as saying that FirstOrDefault() is a code smell not because there is something wrong with it but because it’s being used way too often. This blog post explores the topic in details. IMO most of the times SingleOrDefault() is a much better alternative so watch out for this mistake and make sure you use the most appropriate method that clearly represents your contract and expectations.

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

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

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

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

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

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

结论:

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

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

从本质上讲,这给了你某种验证来清理你的数据,如果你选择其中一个,它会同时给出数据,但SingleOrDefault会让你意识到,当你期望的数据应该只有1个结果,并吐出更多的1,那么你需要看看为什么你的存储过程或查询导致这样,重复的项目在查询中从来都不好。

无论何时使用SingleOrDefault,都明确声明查询最多只能产生一个结果。另一方面,当使用FirstOrDefault时,查询可以返回任意数量的结果,但您声明只想要第一个结果。

我个人认为语义非常不同,根据预期结果使用适当的语义可以提高可读性。

在上一个例子中:

var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or doesn't matter?

是的。如果您尝试使用SingleOrDefault()并且查询结果超过记录,您将得到一个异常。你唯一可以安全使用SingleOrDefault()的时候是当你只期望1和只有1个结果…