实体框架 4 Single() vs First() vs FirstOrDefault()

Posted

技术标签:

【中文标题】实体框架 4 Single() vs First() vs FirstOrDefault()【英文标题】:Entity Framework 4 Single() vs First() vs FirstOrDefault() 【发布时间】:2011-03-29 22:58:45 【问题描述】:

我正在寻找一个比较查询单个项目的不同方法以及何时使用每种方法的比较。

有没有人有一个链接来比较所有这些,或者快速解释一下为什么你会使用一个而不是另一个?还有更多我不知道的运算符吗?

谢谢。

【问题讨论】:

【参考方案1】:

这真的很简单:Single 返回单个项目,如果没有或不止一个项目,则抛出异常。 First 将返回第一个项目或在没有项目时抛出。 FirstOrDefault 将返回第一项或在没有项时返回默认值(如果给定类型是引用类型,则为null)。

这是 API 应该具有的行为。但是请注意,底层实现可能具有不同的行为。虽然 Entity Framework 遵守这一点,但像 LLBLGen 这样的 O/RM 在调用 First 时也可以返回 null,这是一件非常奇怪的事情。这是设计师 IMO 做出的一个非常奇怪(而且很固执)的决定。

【讨论】:

谢谢史蒂文。我想我仍然想知道为什么你会使用一个而不是另一个?我一直使用 FirstOrDefault(),并且很好奇为什么我看到的许多新示例都切换到 Single()。有理由切换到 Single() 吗?有没有其他人也可以完成同样的事情,我应该考虑一下? 如果您希望您的代码“快速失败”,First() 和 Single() 让您的代码更准确地说明预期的内容(否则它可能会失败) 我完全同意弗兰克的观点。这也是关于交流意图。 Single 明确表示您只希望结果有一个元素。【参考方案2】:

以下是不同方法的概述:

Find() - 当您想通过主键获取项目时。如果找不到项目,这将返回 null。它会在进入数据库之前先查看上下文(正如 Yaron 在 cmets 中指出的那样),如果您需要在同一个上下文处于活动状态时多次获取同一个实体,这可能是一个重要的效率因素。

Single() - 当您期望查询只返回一个项目时。如果查询不只返回一个项目,这将引发异常。

SingleOrDefault() - 当您期望查询返回零个或一个项目时(即您不确定具有给定键的项目是否存在)。如果查询没有返回零个或一个项目,这将引发异常。

First() - 当您希望查询返回一个或多个项目但您只想访问代码中的第一项时(排序在此处的查询中可能很重要)。如果查询未返回至少一项,这将引发异常。

FirstOrDefault() - 当您希望查询返回零个或多个项目但您只想访问代码中的第一项时(即您不确定具有给定键的项目是否存在)

【讨论】:

视情况而定。如果您知道对于给定的查询,您应该始终从数据库中获取一条记录,不多也不少,那么 Single() 就是使用的“正确”记录。在其他情况下,其他可能更合适。在以前版本的 EF 中,我们仅限于 First() 和 FirstOrDefault(),它们适用于您期望单个记录的情况,但如果您实际上得到的返回的记录多于该单个记录,它们不会警告您,这可能很重要,具体取决于情况。 谢谢。我再也看不到自己需要 First() 了,而 Single() 不会更好。如果我不那么密集,我相信我仍然可以欣赏/理解何时使用 First()。 First() 在您只想检索排序依据最高或最低的对象的情况下最有意义。例如,找到总价值最高的销售。 Sales.OrderByDescending(s => s.TotalValue).First(); 所有的 cmets 看起来都有一个重要的区别。 Find() 是在访问数据库之前搜索上下文的唯一方法。 另外一点是查询sql数据库时,SingleSingleOrDefault会查询2条记录(限制2),而FirstFirstOrDefault会查询1条(限制1)。 【参考方案3】:

四种方法各有千秋;虽然你真的只有两种不同的操作。

首先 - 期望一个包含多个项目的结果集,给我该集中的第一个项目。 Single - 期待返回一个结果,把那个项目给我。

xxxxOrDefault() 版本只是添加了“我不想将空结果集视为例外情况。”

【讨论】:

好的,所以在我看来 First() 很少能派上用场。我很难想出 Single() 不是首选的方案。碰巧你有一个快速的手头?谢谢。 不幸的是,许多开发人员将 First() 或 FirstOrDefault() 纯粹用作防御措施,认为当它真的有可能隐藏真正的问题时,它会避免异常。【参考方案4】:

我总是倾向于使用FirstOrDefault。如果你真的想对性能很挑剔,那么你应该在 EF 中使用FirstOrDefault。在幕后SingleOrDefault 在查询中使用top (2),因为它需要检查是否有第二行与条件匹配,如果是,则抛出异常。基本上在SingleOrDefault 中,如果您的查询返回多于 1 条记录,您想抛出异常。

【讨论】:

您是否曾经测量过FirstOrDefaultSingleOrDefault 之间的性能差异显着?我会说在大多数情况下这是过早的优化。 当我返回其中应该只存在一个的东西时,我倾向于使用Single()SingleOrDefault()。我这样做的原因是通过编写错误的查询来发现错误,这些查询返回的次数超过了应有的结果,失败了。至少在我看来,这将有助于保持系统中的数据一致。当然这样比较慢,但我猜也不会慢多少,我愿意付出这个代价。【参考方案5】:

Single()SingleOrDefault() 通常用于 ID 等唯一标识符,而 First()FirstOrDefault () 通常用于可能有多个结果但您只需要 "Top 1" 的查询。

如果没有返回结果,

Single()First() 会抛出异常,SingleOrDefault()FirstOrDefault( ) 捕获异常并返回 null 或 default(ResultDataType)。

【讨论】:

【参考方案6】:

另一方面,你可以按照核心逻辑来划分这些方法,像这样:

方法会直接查询数据库Single(), SingleOrDefault(), First(), FirstOrDefault() 在对数据库发出查询之前,该方法将在缓存中执行搜索Find()

有关一些性能细节,尤其是在第二种情况下,您可以查看此处: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

另外,在第一组中你可以定义复杂的查询,但是使用 Find() 方法你可以只提供实体键进行搜索。

【讨论】:

以上是关于实体框架 4 Single() vs First() vs FirstOrDefault()的主要内容,如果未能解决你的问题,请参考以下文章

1.使用Entity Framwork框架常用的技术手段Code First 和Reverse Engineer Code First

实体框架4单()与第()VS FirstOrDefault()

DbContext 代码生成策略在实体框架 5 和 VS 2012 中失败

实体框架 - Code First Bug [关闭]

实体框架-EF Code First Select外键

实体框架 Code First SQL Server 视图